diff --git a/.distignore b/.distignore new file mode 100644 index 000000000..683375753 --- /dev/null +++ b/.distignore @@ -0,0 +1,16 @@ +build +thirdparty +clients + +.git +.gitmodules +.gitignore +.dockerignore + +.DS_Store +*~ + +*.o +*.d + +villas-* \ No newline at end of file diff --git a/.dockerignore b/.dockerignore index bec958ec2..33849337c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,5 @@ * +!build/release/packaging/rpm/* !thirdparty/libxil/ !thirdparty/criterion/ !thirdparty/libwebsockets/ \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e9a1324ab..e35abd861 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,7 +2,6 @@ variables: # This registry is a linked docker container running on the same host # and configured in gitlab-ci-runner config.toml as a linked service DOCKER_REGISTRY: acs-public:5000 - DOCKER_IMAGE: villas:latest PREFIX: /usr/ stages: @@ -15,16 +14,15 @@ stages: ############################################################################## # Build docker image which is used to build & test VILLASnode -docker-image: +docker-images: stage: prepare - # Must match the docker version on the build machine! before_script: - git submodule sync --recursive - git submodule update --recursive --init - docker info script: - - docker build -t $DOCKER_REGISTRY/$DOCKER_IMAGE . - - docker push $DOCKER_REGISTRY/$DOCKER_IMAGE + - make docker-dev + - docker push $DOCKER_REGISTRY/docker-dev tags: - shell - linux @@ -107,14 +105,25 @@ website: tags: - villas-deploy +packaging: + stage: deploy + script: + - make rpm + tags: + - shell + - fedora + deliver: stage: deploy script: - - rsync -r build/release/doc/html/ $DEPLOY_PATH/doc/$CI_BUILD_REF_NAME/ - - rsync -r build/release-coverage/coverage/ $DEPLOY_PATH/coverage/$CI_BUILD_REF_NAME/ + - rsync -r build/release/doc/html/ $DEPLOY_HOST:$DEPLOY_PATH/doc/$CI_BUILD_REF_NAME/ + - rsync -r build/release-coverage/coverage/ $DEPLOY_HOST:$DEPLOY_PATH/coverage/$CI_BUILD_REF_NAME/ + - rsync -r build/release/packaging/rpm/RPMS $DEPLOY_HOST:$DEPLOY_PATH/../packages + - ssh $DEPLOY_HOST createrepo $DEPLOY_PATH/../packages dependencies: - docs - coverage + - packaging tags: - villas-deploy diff --git a/.gitmodules b/.gitmodules index 79fac9332..551d2b3ff 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,6 @@ [submodule "thirdparty/libcurl"] path = thirdparty/libcurl url = https://github.com/curl/curl.git +[submodule "thirdparty/libxil"] + path = thirdparty/libxil + url = git@git.rwth-aachen.de:VILLASframework/libxil.git diff --git a/Dockerfile b/Dockerfile index d3f6d1f00..6b31aae8a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,86 +1,37 @@ -# Dockerfile for VILLASnode development and testing +# Dockerfile for VILLASnode dependencies. # -# Use this Dockerfile running: -# $ make docker +# This Dockerfile builds an image which contains all library dependencies +# and tools to build VILLASnode. +# However, VILLASnode itself it not part of the image. # # @author Steffen Vogel -# @copyright 2016, Institute for Automation of Complex Power Systems, EONERC +# @copyright 2017, Institute for Automation of Complex Power Systems, EONERC ################################################################################### FROM fedora:latest MAINTAINER Steffen Vogel -# Expose ports for HTTP and WebSocket frontend +# Install dependencies +RUN dnf -y update && \ + dnf -y install \ + libconfig \ + libnl3 \ + libcurl \ + jansson + +# Some additional tools required for running VILLASnode +RUN dnf -y update && \ + dnf -y install \ + iproute \ + openssl \ + kernel-modules-extra + +# Install our own RPMs +COPY build/release/packaging/rpm/RPMS/ /rpms/ +RUN rpm -i /rpms/x86_64/{libxil,libwebsockets,villas-node,villas-node-doc}-[0-9]*; rm -rf /rpms/ + +# For WebSocket / API access EXPOSE 80 EXPOSE 443 -# Toolchain & dependencies -RUN dnf -y update && \ - dnf -y install \ - pkgconfig \ - gcc \ - make \ - wget \ - tar \ - cmake \ - openssl-devel \ - libconfig-devel \ - libnl3-devel \ - libcurl-devel \ - jansson-devel - -# Tools for documentation -RUN dnf -y update && \ - dnf -y install \ - doxygen \ - dia \ - graphviz - -# Tools for deployment / packaging -RUN dnf -y update && \ - dnf -y install \ - openssh-clients \ - rpmdevtools \ - rpm-build - -# Tools to build dependencies -RUN dnf -y update && \ - dnf -y install \ - git \ - gcc-c++ \ - autoconf \ - automake \ - autogen \ - libtool \ - flex \ - bison \ - texinfo - -# Tools for coverage and profiling -RUN dnf -y update && \ - dnf -y install \ - python-pip && \ - pip install \ - gcovr - -ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig -ENV LD_LIBRARY_PATH /usr/local/lib - -# Build & Install libxil -COPY thirdparty/libxil /tmp/libxil -RUN mkdir -p /tmp/libxil/build && cd /tmp/libxil/build && cmake .. && make install - -# Build & Install Criterion -COPY thirdparty/criterion /tmp/criterion -RUN mkdir -p /tmp/criterion/build && cd /tmp/criterion/build && cmake .. && make install - -# Build & Install libwebsockets -COPY thirdparty/libwebsockets /tmp/libwebsockets -RUN mkdir -p /tmp/libwebsockets/build && cd /tmp/libwebsockets/build && cmake .. && make install - -# Cleanup intermediate files from builds -RUN rm -rf /tmp/* - -WORKDIR /villas - -ENTRYPOINT make clean && make install && villas node; bash +ENTRYPOINT ["villas"] \ No newline at end of file diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 000000000..15e798543 --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,85 @@ +# Dockerfile for VILLASnode development. +# +# This Dockerfile builds an image which contains all library dependencies +# and tools to build VILLASnode. +# However, VILLASnode itself it not part of the image. +# +# This image can be used for developing VILLASnode +# by running: +# make docker +# +# @author Steffen Vogel +# @copyright 2017, Institute for Automation of Complex Power Systems, EONERC +################################################################################### + +FROM fedora:latest +MAINTAINER Steffen Vogel + +# Toolchain +RUN dnf -y update && \ + dnf -y install \ + gcc pkgconfig make cmake \ + git \ + gcc-c++ \ + autoconf automake autogen libtool \ + flex bison \ + texinfo + +# Dependencies +RUN dnf -y update && \ + dnf -y install \ + openssl \ + openssl-devel \ + libconfig-devel \ + libnl3-devel \ + libcurl-devel \ + jansson-devel + +# Several tools only needed for developement and testing +RUN dnf -y update && \ + dnf -y install \ + doxygen \ + dia \ + graphviz \ + openssh-clients \ + rpmdevtools \ + rpm-build \ + jq \ + iproute \ + python-pip \ + valgrind \ + gdb + +# Tools for debugging, coverage, profiling +RUN pip install \ + gcovr + +ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig +ENV LD_LIBRARY_PATH /usr/local/lib + +# Build & Install libxil +COPY thirdparty/libxil /tmp/libxil +RUN mkdir -p /tmp/libxil/build && cd /tmp/libxil/build && cmake .. && make install + +# Build & Install Criterion +COPY thirdparty/criterion /tmp/criterion +RUN mkdir -p /tmp/criterion/build && cd /tmp/criterion/build && cmake .. && make install + +# Build & Install libwebsockets +COPY thirdparty/libwebsockets /tmp/libwebsockets +RUN mkdir -p /tmp/libwebsockets/build && cd /tmp/libwebsockets/build && cmake .. && make install + +# Cleanup intermediate files from builds +RUN rm -rf /tmp/* + +# Expose ports for HTTP and WebSocket frontend +EXPOSE 80 +EXPOSE 443 + +ADD https://villas.0l.de/packages/villas.repo /etc/yum.repos.d/ + +ENTRYPOINT villas + +WORKDIR /villas + +ENTRYPOINT bash \ No newline at end of file diff --git a/Doxyfile b/Doxyfile index 39536f28f..a1b3a6c16 100644 --- a/Doxyfile +++ b/Doxyfile @@ -51,7 +51,7 @@ PROJECT_BRIEF = "Connecting real-time power grid simulation equipment" # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. -PROJECT_LOGO = doc/pictures/acs_eonerc_logo.svg +PROJECT_LOGO = doc/pictures/villas_node.svg # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is @@ -765,7 +765,7 @@ WARN_LOGFILE = doc/warnings.log # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = src/ lib/ include/ doc/ +INPUT = README.md CONTRIBUTING.md COPYING.md src/ lib/ tests/ include/ doc/ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -906,7 +906,7 @@ FILTER_SOURCE_PATTERNS = # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. -USE_MDFILE_AS_MAINPAGE = doc/Mainpage.md +USE_MDFILE_AS_MAINPAGE = README.md #--------------------------------------------------------------------------- # Configuration options related to source browsing @@ -1126,7 +1126,7 @@ HTML_EXTRA_STYLESHEET = doc/theme/style.css # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_FILES = +HTML_EXTRA_FILES = doc/pictures/acs_eonerc_logo.svg # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to @@ -2196,7 +2196,7 @@ GROUP_GRAPHS = YES # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. -UML_LOOK = NO +UML_LOOK = YES # If the UML_LOOK tag is enabled, the fields and methods are shown inside the # class node. If there are many fields or methods and many nodes the graph may diff --git a/Makefile b/Makefile index 06497e394..f97f20880 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ ################################################################################### # Project modules -MODULES = lib plugins src tests thirdparty tools +MODULES = lib plugins src tests thirdparty tools packaging doc etc web # Default prefix for install target PREFIX ?= /usr/local @@ -28,20 +28,12 @@ V ?= 2 # Common flags LDLIBS = -CFLAGS += -std=c11 -Iinclude -Iinclude/villas -I. -MMD -mcx16 +CFLAGS += -I. -Iinclude -Iinclude/villas +CFLAGS += @$(BUILDDIR)/defines +CFLAGS += -std=c11 -MMD -mcx16 CFLAGS += -Wall -Werror -fdiagnostics-color=auto -CFLAGS += -D_POSIX_C_SOURCE=200809L -D_GNU_SOURCE=1 -DV=$(V) LDFLAGS += -L$(BUILDDIR) -ifdef CI - CFLAGS += -D_GIT_REV='"${CI_BUILD_REF:0:7}~ci"' -else - GIT = $(shell type -p git) - ifneq ($(GIT),) - CFLAGS += -D_GIT_REV='"$(shell git rev-parse --short HEAD)"' - endif -endif - # We must compile without optimizations for gcov! ifdef DEBUG CFLAGS += -O0 -g @@ -69,49 +61,72 @@ ifdef COVERAGE VARIANTS += coverage endif -SPACE := -SPACE += -BUILDDIR := $(BUILDDIR)/$(subst $(SPACE),-,$(strip $(VARIANTS))) +EMPTY := +SPACE := $(EMPTY) $(EMPTY) +VARIANT = $(subst $(SPACE),-,$(strip $(VARIANTS))) +BUILDDIR := $(BUILDDIR)/$(VARIANT) SRCDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) +# Add git revision and build variant defines +VERSION = $(shell git describe --tags --abbrev=0 --match v*) +VERSION_NUM = $(shell VERSION=$(VERSION); echo $${VERSION:1}) + +ifdef CI + GIT_REV = ${CI_BUILD_REF:0:7} + VARIANT = ci-$(VARIANT) +else + GIT_REV = $(shell REV=$$(git rev-parse HEAD); echo $${REV:0:7}) +endif + + # pkg-config dependencies PKGS = libconfig ######## Targets ######## # Add flags by pkg-config -CFLAGS += $(addprefix -DWITH_, $(shell echo ${PKGS} | tr a-z- A-Z_ | tr -dc ' A-Z0-9_' )) CFLAGS += $(shell pkg-config --cflags ${PKGS}) LDLIBS += $(shell pkg-config --libs ${PKGS}) -all: src plugins | lib +all: src plugins tools +# Build all variants: debug, coverage, ... everything: + $(MAKE) RELEASE=1 $(MAKE) DEBUG=1 $(MAKE) COVERAGE=1 $(MAKE) PROFILE=1 - $(MAKE) doc - $(MAKE) tests - -install: $(addprefix install-,$(MODULES)) - -clean: $(addprefix clean-,$(MODULES)) - -docker: - docker build -t villas . - docker run -it -p 80:80 -p 443:443 -p 1234:1234 --privileged --cap-add sys_nic --ulimit memlock=1073741824 --security-opt seccomp:unconfined -v $(PWD):/villas villas - -doc: | $(BUILDDIR)/doc/ - ( cat Doxyfile ; echo "OUTPUT_DIRECTORY=$(BUILDDIR)/doc/" ) | doxygen - # Create non-existent directories +.SECONDEXPANSION: +.PRECIOUS: %/ %/: mkdir -p $@ -.PHONY: all everything clean install docker doc -.PRECIOUS: %/ -.SECONDEXPANSION: +define DEFINES +-DV=$(V) + +-DPLUGIN_PATH=\"$(PREFIX)/share/villas/node/plugins\" +-DWEB_PATH=\"$(PREFIX)/share/villas/node/web\" +-DSYSFS_PATH=\"/sys\" +-DPROCFS_PATH=\"/proc\" +-DBUILDID=\"$(VERSION)-$(GIT_REV)-$(VARIANT)\" + +-D_POSIX_C_SOURCE=200809L +-D_GNU_SOURCE=1 +endef +export DEFINES + +$(BUILDDIR)/defines: | $$(dir $$@) + echo "$${DEFINES}" > $@ + echo -e "$(addprefix \n-DWITH_, $(shell echo ${PKGS} | tr a-z- A-Z_ | tr -dc ' A-Z0-9_' ))" >> $@ + echo -e "$(addprefix \n-DWITH_, $(shell echo ${LIB_PKGS} | tr a-z- A-Z_ | tr -dc ' A-Z0-9_' ))" >> $@ + +install: $(addprefix install-,$(filter-out thirdparty doc,$(MODULES))) +clean: $(addprefix clean-,$(filter-out thirdparty doc,$(MODULES))) + +.PHONY: all everything clean install -include $(wildcard $(BUILDDIR)/**/*.d) --include $(addsuffix /Makefile.inc,$(MODULES)) +-include $(addsuffix /Makefile.inc,$(MODULES)) \ No newline at end of file diff --git a/README.md b/README.md index 1faecce2e..68ff8db46 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,53 @@ -# VILLASnode [![build status](https://git.rwth-aachen.de/acs/VILLASnode/badges/develop/build.svg)](https://git.rwth-aachen.de/acs/VILLASnode/commits/develop) [![coverage report](https://git.rwth-aachen.de/acs/VILLASnode/badges/develop/coverage.svg)](https://git.rwth-aachen.de/acs/VILLASnode/commits/develop) +# VILLASnode +[![build status](https://git.rwth-aachen.de/VILLASframework/VILLASnode/badges/develop/build.svg)](https://git.rwth-aachen.de/acs/VILLASnode/commits/develop) +[![coverage report](https://git.rwth-aachen.de/VILLASframework/VILLASnode/badges/develop/coverage.svg)](https://git.rwth-aachen.de/acs/VILLASnode/commits/develop) This is VILLASnode, a gateway for processing and forwardning simulation data between real-time simulators. +VILLASnode is a client/server application to connect simulation equipment and software such as: + - OPAL-RT eMegaSim, + - RTDS GTFPGA cards, + - Simulink, + - LabView, + - and FPGA models. -## Documentation +It's designed with a focus on very low latency to achieve almost realtime exchange of simulation data. +VILLASnode is used in distributed- and co-simulation scenarios and developed for the field of power grid simulation at the EON Energy Research Center in Aachen, Germany. -The documentation for this software is available at [doc/Mainpage](doc/Mainpage.md). +## Overview -The full documentation is available at [doc/html/index.html](doc/html/index.html) after running `doxygen` in this directory. +The project consists of a server daemon and several client modules which are documented here. -You can access the prebuild documentation at: http://134.130.169.32/villas/node/ (available only from ACS *Office network* and *Simulation Network*). +[TOC] + +### Server + +The server simply acts as a gateway to forward simulation data from one client to another. +Furthermore, it collects statistics, monitors the quality of service and handles encryption or tunneling through VPNs. + +For optimal performance the server is implemented in low-level C and makes use of several Linux-specific realtime features. +The primary design goal was to make the behaviour of the system as deterministic as possible. + +Therefore, it's advisable to run the server component on a [PREEMPT_RT](https://rt.wiki.kernel.org/index.php/CONFIG_PREEMPT_RT_Patch) patched version of Linux. In our environment, we use Fedora-based distribution which has been stripped to the bare minimum (no GUI, only a few background processes). + +The server is a multi-threaded application. + +### Clients + +There are two types of clients: + +1. The server handles diffrent types of nodes. + The most commonly used node-type is the 'socket' type which allows communication over network links (UDP, raw IP, raw Ethernet frames). + But there are also other specialized node types to retreive or send data to equipemnt, which is directly connected to or running on the server itself. + An example for such a node is the 'gtfpga' type which directly fetches and pushes data to a PCIe card. + Or the 'file' type which logs or replays simulation data from the harddisk. + +2. An other way to connect simulation equipment is by using a client-application which itself sends the data over the network to VILLASnode. + In this scenario, VILLASnode uses the 'socket' node-type to communicate with the client-application. + +Usually, new clients / equipemnt should be implemented as a new node-type as part of VILLASnode. +Using a dedicated client-application which communicates via the 'socket' type is deprecated because it leads to code duplication. ## Contact diff --git a/clients/opal/udp/models/send_receive/include/msg.h b/clients/opal/udp/models/send_receive/include/msg.h index e68bd1b26..ee00377ab 100644 --- a/clients/opal/udp/models/send_receive/include/msg.h +++ b/clients/opal/udp/models/send_receive/include/msg.h @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #ifndef _MSG_H_ diff --git a/clients/opal/udp/models/send_receive/include/msg_format.h b/clients/opal/udp/models/send_receive/include/msg_format.h index 72951d01f..2b1b5cc79 100644 --- a/clients/opal/udp/models/send_receive/include/msg_format.h +++ b/clients/opal/udp/models/send_receive/include/msg_format.h @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #ifndef _MSG_FORMAT_H_ diff --git a/clients/opal/udp/models/send_receive/include/utils.h b/clients/opal/udp/models/send_receive/include/utils.h index bc70e4f0f..f1c387d50 100644 --- a/clients/opal/udp/models/send_receive/include/utils.h +++ b/clients/opal/udp/models/send_receive/include/utils.h @@ -4,7 +4,7 @@ * @author Steffen Vogel * @author Mathieu Dubé-Dallaire * @copyright 2003, OPAL-RT Technologies inc - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #ifndef _UTILS_H_ diff --git a/clients/opal/udp/models/send_receive/src/msg.c b/clients/opal/udp/models/send_receive/src/msg.c index 5c2bf19a8..dd472514e 100644 --- a/clients/opal/udp/models/send_receive/src/msg.c +++ b/clients/opal/udp/models/send_receive/src/msg.c @@ -1,7 +1,7 @@ /** Message related functions. * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #ifdef __linux__ diff --git a/clients/opal/udp/models/send_receive/src/utils.c b/clients/opal/udp/models/send_receive/src/utils.c index 645124740..e8c599807 100644 --- a/clients/opal/udp/models/send_receive/src/utils.c +++ b/clients/opal/udp/models/send_receive/src/utils.c @@ -4,7 +4,7 @@ * @author Steffen Vogel * @author Mathieu Dubé-Dallaire * @copyright 2003, OPAL-RT Technologies inc - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/GTNETSKT1_to.txt b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/GTNETSKT1_to.txt similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/GTNETSKT1_to.txt rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/GTNETSKT1_to.txt diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/GTNET_SKT_TCP_GUI.java b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/GTNET_SKT_TCP_GUI.java similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/GTNET_SKT_TCP_GUI.java rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/GTNET_SKT_TCP_GUI.java diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/GTNET_SKT_UDP_GUI.java b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/GTNET_SKT_UDP_GUI.java similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/GTNET_SKT_UDP_GUI.java rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/GTNET_SKT_UDP_GUI.java diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/HowToRunTheGTNET_SKT_UDPExample.txt b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/HowToRunTheGTNET_SKT_UDPExample.txt similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/HowToRunTheGTNET_SKT_UDPExample.txt rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/HowToRunTheGTNET_SKT_UDPExample.txt diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/SoftEdgeBorder.java b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/SoftEdgeBorder.java similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/SoftEdgeBorder.java rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/SoftEdgeBorder.java diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/SoftEdgeButton.java b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/SoftEdgeButton.java similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/SoftEdgeButton.java rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/SoftEdgeButton.java diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_tcp.dft b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_tcp.dft similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_tcp.dft rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_tcp.dft diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_tcp.dft.1 b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_tcp.dft.1 similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_tcp.dft.1 rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_tcp.dft.1 diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_tcp.dft.2 b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_tcp.dft.2 similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_tcp.dft.2 rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_tcp.dft.2 diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_tcp.sib b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_tcp.sib similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_tcp.sib rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_tcp.sib diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.bat b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.bat similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.bat rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.bat diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.dft b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.dft similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.dft rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.dft diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.dft.1 b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.dft.1 similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.dft.1 rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.dft.1 diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.dft.2 b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.dft.2 similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.dft.2 rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.dft.2 diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.dtp b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.dtp similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.dtp rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.dtp diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.inf b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.inf similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.inf rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.inf diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.inf2 b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.inf2 similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.inf2 rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.inf2 diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.log b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.log similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.log rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.log diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.map b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.map similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.map rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.map diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.pUsage b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.pUsage similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.pUsage rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.pUsage diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.sib b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.sib similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.sib rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp.sib diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp_r7 b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp_r7 similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp_r7 rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp_r7 diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp_tx7.txt b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp_tx7.txt similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp_tx7.txt rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback/gtnet_skt_2point_udp_tx7.txt diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/GTNETSKT1_to.txt b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/GTNETSKT1_to.txt similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/GTNETSKT1_to.txt rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/GTNETSKT1_to.txt diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/GTNET_SKT_TCP_GUI.java b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/GTNET_SKT_TCP_GUI.java similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/GTNET_SKT_TCP_GUI.java rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/GTNET_SKT_TCP_GUI.java diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/GTNET_SKT_UDP_GUI.java b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/GTNET_SKT_UDP_GUI.java similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/GTNET_SKT_UDP_GUI.java rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/GTNET_SKT_UDP_GUI.java diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/HowToRunTheGTNET_SKT_UDPExample.txt b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/HowToRunTheGTNET_SKT_UDPExample.txt similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/HowToRunTheGTNET_SKT_UDPExample.txt rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/HowToRunTheGTNET_SKT_UDPExample.txt diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/SoftEdgeBorder.java b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/SoftEdgeBorder.java similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/SoftEdgeBorder.java rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/SoftEdgeBorder.java diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/SoftEdgeButton.java b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/SoftEdgeButton.java similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/SoftEdgeButton.java rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/SoftEdgeButton.java diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_tcp.dft b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_tcp.dft similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_tcp.dft rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_tcp.dft diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_tcp.dft.1 b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_tcp.dft.1 similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_tcp.dft.1 rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_tcp.dft.1 diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_tcp.dft.2 b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_tcp.dft.2 similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_tcp.dft.2 rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_tcp.dft.2 diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_tcp.sib b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_tcp.sib similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_tcp.sib rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_tcp.sib diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.bat b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.bat similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.bat rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.bat diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.dft b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.dft similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.dft rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.dft diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.dft.1 b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.dft.1 similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.dft.1 rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.dft.1 diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.dft.2 b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.dft.2 similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.dft.2 rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.dft.2 diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.dtp b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.dtp similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.dtp rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.dtp diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.inf b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.inf similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.inf rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.inf diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.inf2 b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.inf2 similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.inf2 rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.inf2 diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.log b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.log similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.log rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.log diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.map b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.map similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.map rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.map diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.pUsage b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.pUsage similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.pUsage rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.pUsage diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.sib b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.sib similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.sib rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp.sib diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp_r7 b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp_r7 similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp_r7 rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp_r7 diff --git a/clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp_tx7.txt b/clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp_tx7.txt similarity index 100% rename from clients/RTDS/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp_tx7.txt rename to clients/rtds/GTNETv2_SKT/Standard_2pt_udp_loopback_gtsync/gtnet_skt_2point_udp_tx7.txt diff --git a/config.h b/config.h index 45c1920c1..6a5d9bd1c 100644 --- a/config.h +++ b/config.h @@ -5,23 +5,19 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ -#ifndef _CONFIG_H_ -#define _CONFIG_H_ - -#ifndef _GIT_REV - #define _GIT_REV "nogit" -#endif - -/** The version number of VILLASnode */ -#define VERSION "v0.6-" _GIT_REV +#pragma once /** Default number of values in a sample */ #define DEFAULT_VALUES 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 25 + /** Width of log output in characters */ #define LOG_WIDTH 132 @@ -32,24 +28,12 @@ #define IPPROTO_VILLAS 137 #define ETH_P_VILLAS 0xBABE -#define SYSFS_PATH "/sys" -#define PROCFS_PATH "/proc" +#define USER_AGENT "VILLASnode (" BUILDID ")" -/* Required kernel version */ +/*ID Required kernel version */ #define KERNEL_VERSION_MAJ 3 #define KERNEL_VERSION_MIN 6 -/* Some hard-coded configuration for the FPGA benchmarks */ -#define BENCH_DM 3 -// 1 FIFO -// 2 DMA SG -// 3 DMA Simple - -#define BENCH_RUNS 3000000 -#define BENCH_WARMUP 100 -#define BENCH_DM_EXP_MIN 0 -#define BENCH_DM_EXP_MAX 20 - /** PCIe BAR number of VILLASfpga registers */ #define FPGA_PCI_BAR 0 #define FPGA_PCI_VID_XILINX 0x10ee @@ -57,14 +41,4 @@ /** 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 - -/** Global configuration */ -struct settings { - int priority; /**< Process priority (lower is better) */ - int affinity; /**< Process affinity of the server and all created threads */ - int debug; /**< Debug log level */ - double stats; /**< Interval for path statistics. Set to 0 to disable themo disable them. */ -}; - -#endif /* _CONFIG_H_ */ +#define FPGA_AXI_HZ 125000000 // 125 MHz \ No newline at end of file diff --git a/doc/AdvancedIO.md b/doc/AdvancedIO.md new file mode 100644 index 000000000..0100e9978 --- /dev/null +++ b/doc/AdvancedIO.md @@ -0,0 +1,54 @@ +# Advanced IO {#advio} + +__This page is intended for developers only__ + +Implements an fopen() abstraction allowing reading from URIs. + +This file introduces a c library buffered I/O interface to URI reads it supports fopen(), fread(), fgets(), feof(), fclose(), rewind(). Supported functions have identical prototypes to their normal libc namesakes and are preceaded by 'a'. + +Using this code you can replace your program's fopen() with afopen() and fread() with afread() and it become possible to read remote streams instead of (only) local files. Local files (ie those that can be directly fopened) will drop back to using the underlying libc implementations. + +Advanced IO (ADVIO) is an extension of the standard IO features (STDIO) which can operate on files stored remotely via a variety of different protocols. +As ADVIO is built upon libcurl, it supports all of [libcurl protocols](https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html). + +When openeing a file with ADVIO, the file is requested from the remote server and stored as a local temporary file on the disk. +Subsequent operations use this local copy of the file. +When closing or flushing the file, the local copy gets checked for modifications and uploaded to the remote. + + There are a few points to keep in mind: + + - `afflush()` uploads the file contents to its origin URI if it was changed locally. + - `afclose()` flushes (and hence uploads) the file only if it has been modified. Modifications are detected by comparing the files SHA1 hashes. + +## Extensions + +The following functions have been added: + +- `aupload()` uploads the file irrespectively if it was changed or not. +- `adownload()` downloads the file and discards any local changes. +- `auri()` returns a pointer to the URI. +- `ahash()` returns a pointer to a + +## Example + + #include + + AFILE *f; + char buf[1024]; + + f = afopen("ftp://user:passwd@server/path/to/file.txt", "r"); + if (!f) + serror("Failed to open file"); + + afread(buf, 1, 1024, f); + + printf("%s", buf); + + afclose(f); + +## Usage for VILLASnode + +VILLASnode uses ADVIO currently for: + +- Fetchting the configuration file. This means VILLASnode can be started like `villas-node http://server/config.conf` +- As source and destination file for the `file` node-type. Please have a look at the example configuration file `etc/advio.conf`. \ No newline at end of file diff --git a/doc/Concept.md b/doc/Concept.md index 5d03ceb10..a2b0beb48 100644 --- a/doc/Concept.md +++ b/doc/Concept.md @@ -1,12 +1,14 @@ # Concept -The server is designed around the concept of _nodes_ and _paths_. +VILLASnode is designed around the concept of _nodes_, _super-nodes_ and _paths_. It's the task of the server to forward real-time simulation data between multiple parties. In doing so, the server has to perform simple checks and collects statistics. From the viewpoint of the communication parters the server is nearly transparent. Hence, it's cruical to keep the added overhead as low as possible (in terms of latency). -## Nodes +## @subpage supernode + +## @subpage node All communication partners are represented by nodes. @@ -19,7 +21,7 @@ Possible types of nodes are: @see node for implementation details. -## Paths +## @subpage path A path is a **uni-directional** connection between incoming and outgoing nodes. @@ -36,6 +38,8 @@ However every path supports optional hook/callback functions which allow user-de @see path for implementation details. +## @subpage hook + ## Interface Interfaces are used to represent physical network ports on the server. diff --git a/doc/Contributing.md b/doc/Contributing.md deleted file mode 120000 index 44fcc6343..000000000 --- a/doc/Contributing.md +++ /dev/null @@ -1 +0,0 @@ -../CONTRIBUTING.md \ No newline at end of file diff --git a/doc/Development.md b/doc/Development.md index 00d811569..ee76b4384 100644 --- a/doc/Development.md +++ b/doc/Development.md @@ -1,40 +1,54 @@ # Development -Developement is currently coordinated by Steffen Vogel using [GitHub](http://github.com/RWTH-ACS/VILLASnode). +Developement is currently coordinated by Steffen Vogel using [GitLab](http://git.rwth-aachen.de/VILLASframework/VILLASnode). Please feel free to submit pull requests or bug reports. +@todo Add link to contribution guidelines + +## Programming Paradigm + +VILLASnode is currently written in C using the ISO C99 standard. +Yet, it is heavily structured into modules / plugins and uses a C++-like object oriented style. +In the future, VILLASnode might switch to lightweight C++. + +Main _classes_ in VILLASnode are struct node, struct path, struct hook and struct api_ressource. +In order to track the life cycle of those objects, each of them has an enum state member. +The following figure illustrates the state machine which is used: + +@diafile states.dia + ## Shared library: libvillas -VILLASnode is split into a shared library called libvillas and a couple of executables (`villas-server`, `villas-pipe`, `villas-test`, `villas-signal`) which are linked agains the library. +VILLASnode is split into a shared library called libvillas and a couple of executables (`villas-node`, `villas-pipe`, `villas-test`, `villas-signal`, ...) which are linked against this library. -## Extensibilty +## Extensibilty / Plugins -There are two main places where VILLASnode can easily extended: +There are many places where VILLASnode can easily extended with plugins: -#### New node-type +### Example of new node type - REGISTER_NODE_TYPE(struct node_type *vt) +See `include/villas/plugin.h` -#### New hook functions +See `lib/nodes/file.c`: - /** The type of a hook defines when a hook will be exectuted. This is used as a bitmask. */ - enum hook_type { - HOOK_PATH_START = 1 << 0, /**< Called whenever a path is started; before threads are created. */ - [...] - HOOK_ASYNC = 1 << 6, /**< Called asynchronously with fixed rate (see path::rate). */ + static struct plugin p = { + .name = "file", + .description = "support for file log / replay node type", + .type = PLUGIN_TYPE_NODE, + .node = { + .vectorize = 1, + .size = sizeof(struct file), + .reverse = file_reverse, + .parse = file_parse, + .print = file_print, + .start = file_start, + .stop = file_stop, + .read = file_read, + .write = file_write, + .instances = LIST_INIT() + } + }; - HOOK_PERIODIC = 1 << 7, /**< Called periodically. Period is set by global 'stats' option in the configuration file. */ - - /** @{ Classes of hooks */ - /** Internal hooks are mandatory. */ - HOOK_INTERNAL = 1 << 16, - /** All hooks */ - HOOK_ALL = HOOK_INTERNAL - 1 - /** @} */ - }; - - typedef int (*hook_cb_t)(struct path *p, struct hook *h, int when); - - REGISTER_HOOK(char *name, int priority, hook_cb_t cb, enum hook_type when) + REGISTER_PLUGIN(&p) \ No newline at end of file diff --git a/doc/GettingStarted.md b/doc/GettingStarted.md index 363c462e2..78201b0b9 100644 --- a/doc/GettingStarted.md +++ b/doc/GettingStarted.md @@ -15,7 +15,9 @@ We prepared a image which you can download and run out of the box: 3. Start the latest VILLASnode container by running: - $ docker run rwthacs/villas + $ git clone --recursive git@git.rwth-aachen.de:VILLASframework/VILLASnode.git + $ cd VILLASnode + $ make docker ### To be added @@ -24,8 +26,7 @@ VILLASnode ... - is written in object-oriented C11 - is compiled with Clang / LLVM or GCC - is fully based on open source software -- stands for Simulator-to-Simulator-Server -- is extensible with new node types -- heavily multi-threaded +- is extensible with new node types & hooks +- is heavily multi-threaded - follows the Unix philosophy -- is separated into a library (libvillas) and a few binaries (server, pipe, test, signal) which link against the lib. \ No newline at end of file +- is separated into a library (libvillas) and a few binaries (villas-server, villas-pipe, villas-test-*, villas-signal, villas-hook) which link against the lib. \ No newline at end of file diff --git a/doc/Install.md b/doc/Install.md index 204519322..45833121e 100644 --- a/doc/Install.md +++ b/doc/Install.md @@ -1,10 +1,8 @@ # Setup -## Compilation +## Prerequisites -### Prerequisites - -Install libraries and developement headers for: +For all features VILLASnode currently requires the following list of dependencies: - [libconfig](http://www.hyperrealm.com/libconfig/) for parsing the configuration file. - [libnl3](http://www.infradead.org/~tgr/libnl/) for the network communication & emulation support of the `socket` node-type. @@ -13,6 +11,10 @@ Install libraries and developement headers for: - [libwebsockets](http://libwebsockets.org) for the `websocket` node-type. - [libcurl](https://curl.haxx.se/libcurl/) for HTTP REST requests by the `ngsi` node-type. +There are two ways to install these dependencies: + +1. You can most of the dependencies using the package manger of your Linux distribution: + Use the following command to install the dependencies under Debian-based distributions: $ sudo apt-get install build-essential pkg-config wget tar cmake doxygen dia graphviz libconfig-dev libnl-3-dev libnl-route-3-dev libjansson-dev libcurl4-openssl-dev @@ -20,8 +22,15 @@ Use the following command to install the dependencies under Debian-based distrib or the following line for Fedora / CentOS / Redhat systems: $ sudo yum install gcc pkgconfig make wget tar cmake openssl-devel doxygen dia graphviz libconfig-devel libnl3-devel libcurl-devel jansson-devel + + 2. Alternatively, you can use the make targets `make thirdparty` and `make install-thirdparty` which will compile and install all required dependencies from source. + +## Fetching VILLASnode -### Compilation + $ git clone --recursive git@git.rwth-aachen.de:VILLASframework/VILLASnode.git + $ cd VILLASnode + +## Compilation Checkout the `Makefile` and `include/config.h` for some options which have to be specified at compile time. @@ -32,7 +41,7 @@ Afterwards, start the compilation with: Append `V=5` to `make` for a more verbose debugging output. Append `DEBUG=1` to `make` to add debug symbols. -### Installation +## Installation Install the files to your search path: @@ -40,10 +49,10 @@ Install the files to your search path: Append `PREFIX=/opt/local` to change the installation destination. -### Test +## Test Verify everything is working and required node-types are compiled-in: - $ villas server + $ villas node Will show you the current version of the server including a list of all supported node-types. diff --git a/doc/License.md b/doc/License.md deleted file mode 120000 index 0c9476f2b..000000000 --- a/doc/License.md +++ /dev/null @@ -1 +0,0 @@ -../COPYING.md \ No newline at end of file diff --git a/doc/LiveSystem.md b/doc/LiveSystem.md deleted file mode 100644 index 714e884bb..000000000 --- a/doc/LiveSystem.md +++ /dev/null @@ -1,7 +0,0 @@ -# LiveCD & LiveUSB - -As described in the [Tuning](Tuning) page, a carefull setup of the underlying system is essential to get optimal performance. - -At ACS, we are using a Fedora-based Live system which is optomized for real-time critical workloads. - -Take a look at the `contrib/liveusb/` directory for the configuration and scripts we are using. diff --git a/doc/Mainpage.md b/doc/Mainpage.md deleted file mode 100644 index 42b376f97..000000000 --- a/doc/Mainpage.md +++ /dev/null @@ -1,51 +0,0 @@ -VILLASnode is a client/server application to connect simulation equipment and software such as: - - - OPAL-RT eMegaSim, - - RTDS GTFPGA cards, - - Simulink, - - LabView, - - and FPGA models. - -It's designed with a focus on very low latency to achieve almost realtime exchange of simulation data. -VILLASnode is used in distributed- and co-simulation scenarios and developed for the field of power grid simulation at the EON Energy Research Center in Aachen, Germany. - -## Overview - -The project consists of a server daemon and several client modules which are documented here. - -[TOC] - -### Server - -The server simply acts as a gateway to forward simulation data from one client to another. -Furthermore, it collects statistics, monitors the quality of service and handles encryption or tunneling through VPNs. - -For optimal performance the server is implemented in low-level C and makes use of several Linux-specific realtime features. -The primary design goal was to make the behaviour of the system as deterministic as possible. - -Therefore, it's advisable to run the server component on a [PREEMPT_RT](https://rt.wiki.kernel.org/index.php/CONFIG_PREEMPT_RT_Patch) patched version of Linux. In our environment, we use Fedora-based distribution which has been stripped to the bare minimum (no GUI, only a few background processes). - -The server is a multi-threaded application. - -### Clients - -There are two types of clients: - -1. The server handles diffrent types of nodes. - The most commonly used node-type is the 'socket' type which allows communication over network links (UDP, raw IP, raw Ethernet frames). - But there are also other specialized node types to retreive or send data to equipemnt, which is directly connected to or running on the server itself. - An example for such a node is the 'gtfpga' type which directly fetches and pushes data to a PCIe card. - Or the 'file' type which logs or replays simulation data from the harddisk. - -2. An other way to connect simulation equipment is by using a client-application which itself sends the data over the network to VILLASnode. - In this scenario, VILLASnode uses the 'socket' node-type to communicate with the client-application. - -Usually, new clients / equipemnt should be implemented as a new node-type as part of VILLASnode. -Using a dedicated client-application which communicates via the 'socket' type is deprecated because it leads to code duplication. - -## Contact - -This project is developed at the [Institute for Automation of Complex Power Systems](www.acs.eonerc.rwth-aachen.de) (ACS), EON Energy Research Center (EONERC) at the [RWTH University](http://www.rwth-aachen.de) in Aachen, Germany. - - - Steffen Vogel - - Marija Stevic diff --git a/doc/Makefile.inc b/doc/Makefile.inc new file mode 100644 index 000000000..b57d906e6 --- /dev/null +++ b/doc/Makefile.inc @@ -0,0 +1,11 @@ +doc: | $(BUILDDIR)/doc/ + ( cat Doxyfile ; echo "OUTPUT_DIRECTORY=$(BUILDDIR)/doc/" ) | doxygen - + +install-doc: doc + mkdir -p $(DESTDIR)$(PREFIX)/share/villas/node/doc/ + cp -R $(BUILDDIR)/doc/html/* $(DESTDIR)$(PREFIX)/share/villas/node/doc/ + +clean-doc: + rm -rf $(BUILDDIR)/doc/ + +.PHONY: doc install-doc clean-doc \ No newline at end of file diff --git a/doc/Nodes.md b/doc/Nodes.md index c2c8f111c..9b59dfbf7 100644 --- a/doc/Nodes.md +++ b/doc/Nodes.md @@ -3,8 +3,8 @@ Every server needs clients which act as sinks / sources for simulation data. In case of VILLASnode these clients are called _nodes_. Every node is an instance of a node-type. VILLASnode currently supports the following node-types: -#### @subpage gtfpga - - RTDS via GTFPGA and PCIexpress (Linux vfio, uio) +#### @subpage villasfpga + - VILLASfpga sub-project connect RTDS via GTFPGA and PCIexpress (Linux vfio, uio) #### @subpage opal - OPAL via Asynchronous Process (libOpalAsyncApi) @@ -24,4 +24,7 @@ Every node is an instance of a node-type. VILLASnode currently supports the foll - NGSI 9/10 a.k.a. FIRWARE context broker #### @subpage labview - - NI LabView RT-targets \ No newline at end of file + - NI LabView RT-targets + +#### @subpage cbuilder +- RTDS CBuilder Control System components \ No newline at end of file diff --git a/doc/Readme.md b/doc/Readme.md deleted file mode 120000 index 32d46ee88..000000000 --- a/doc/Readme.md +++ /dev/null @@ -1 +0,0 @@ -../README.md \ No newline at end of file diff --git a/doc/RemoteAPI.md b/doc/RemoteAPI.md new file mode 100644 index 000000000..4f6fbadaa --- /dev/null +++ b/doc/RemoteAPI.md @@ -0,0 +1,101 @@ +#Remote Application Programming Interface (API) {#API} + +VILLASnode can be controlled remotely over a HTTP REST / WebSocket API. +This page documents this API. + +## Transports + +The API is accessible via multiple transports: + +- via HTTP POST requests +- via a WebSocket protocol +- via a Unix socket + +All transports use the same JSON based protocol to handle requests. + +### HTTP REST + +**Endpoint URL:** http[s]://localhost:80/api/v1 +**HTTP Method:** POST + +### WebSockets + +**WebSocket Protocol:** `api` + +### Unix socket + +_This transport is not implemented yet_ + +## Commands + +### `reload` + +Restart VILLASnode with a new configuration file. + +**Request:** _application/json_ + + { + "request": "reload", + "id": "edei4shahNgucoo7paeth8chue0iyook" + "configuration": "smb://MY-WINDOWS-HOST/SHARE1/path/to/config.conf" + } + +**Response:** _application/json_ + + { + "response": "reload", + "id": "edei4shahNgucoo7paeth8chue0iyook", + "status": "success" + } + +### `config` + +Retrieve the contents of the current configuration. + +**Request:** _application/json_ + + { + "request": "config", + "id": "oom3lie7nee4Iepieng8ae4ueToebeki" + "configuration": "smb://MY-WINDOWS-HOST/SHARE1/path/to/config.conf" + } + +**Response:** _application/json_ + + { + "response": "config", + "id": "oom3lie7nee4Iepieng8ae4ueToebeki", + "config" : { + "nodes" : { + "socket_node" : { + "type": "socket", + "layer": "udp", + ... + } + }, + "paths" : [ + { + "in": "socket_node", + "out": "socket_node" + } + ] + } + } + +### `nodes` + +Get a list of currently active nodes. + +_This request is not implemented yet_ + +### `paths` + +Get a list of currently active paths. + +_This request is not implemented yet_ + +### `status` + +The the status of this VILLASnode instance. + +_This request is not implemented yet_ \ No newline at end of file diff --git a/doc/Usage.md b/doc/Usage.md index 093dbcd92..45fb7f46b 100644 --- a/doc/Usage.md +++ b/doc/Usage.md @@ -1,13 +1,42 @@ # Usage {#usage} -VILLASnode (`villas node`) expects the path to a configuration file as a single argument. +The core of VILLASnode is the `villas-node` server. +The folling usage information is provided when called like `villas-node --help`; - Usage: ./villas-node CONFIG - CONFIG is a required path to a configuration file - - VILLASnode 0.1-d7de19c (Jun 4 2014 02:50:13) - Copyright 2015, Institute for Automation of Complex Power Systems, EONERC - Steffen Vogel + Usage: villas-node [CONFIG] + CONFIG is the path to an optional configuration file + if omitted, VILLASnode will start without a configuration + and wait for provisioning over the web interface. + + Supported node types: + - file : support for file log / replay node type + - cbuilder : RTDS CBuilder model + - socket : BSD network sockets + - fpga : VILLASfpga PCIe card (libxil) + - ngsi : OMA Next Generation Services Interface 10 (libcurl, libjansson) + - websocket : Send and receive samples of a WebSocket connection (libwebsockets) + + Supported hooks: + - restart : Call restart hooks for current path + - print : Print the message to stdout + - decimate : Downsamping by integer factor + - fix_ts : Update timestamps of sample if not set + - skip_first : Skip the first samples + - drop : Drop messages with reordered sequence numbers + - convert : Convert message from / to floating-point / integer + - shift : Shift the origin timestamp of samples + - ts : Update timestamp of message with current time + - stats : Collect statistics for the current path + - stats_send : Send path statistics to another node + + Supported API commands: + - nodes : retrieve list of all known nodes + - config : retrieve current VILLASnode configuration + - reload : restart VILLASnode with new configuration + + VILLASnode v0.7-0.2-646-g59756e7-dirty-debug (built on Mar 12 2017 21:37:40) + copyright 2014-2016, Institute for Automation of Complex Power Systems, EONERC + Steffen Vogel The server requires root privileges for: @@ -40,7 +69,7 @@ The server requires root privileges for: 4. Edit configuration file - $ nano etc/opal-test.conf + $ nano etc/loopback.conf - Take a look at the examples and documentation for a detailed description - Move with: cursor keys @@ -48,7 +77,7 @@ The server requires root privileges for: 5. Start server - $ villas node etc/opal-test.conf + $ villas node etc/loopback.conf 6. Terminate server by pressing Ctrl+C diff --git a/doc/Hooks.md b/doc/concept/Hooks.md similarity index 99% rename from doc/Hooks.md rename to doc/concept/Hooks.md index 6ec3b9828..e85d41ab4 100644 --- a/doc/Hooks.md +++ b/doc/concept/Hooks.md @@ -1,4 +1,4 @@ -# Hooks +# Hooks {#hook} Hooks are simple callback functions which are called whenever a message is processed by a path. diff --git a/doc/concept/Node.md b/doc/concept/Node.md new file mode 100644 index 000000000..66c18daae --- /dev/null +++ b/doc/concept/Node.md @@ -0,0 +1 @@ +#Nodes {#node} \ No newline at end of file diff --git a/doc/concept/Path.md b/doc/concept/Path.md new file mode 100644 index 000000000..1a74a2a63 --- /dev/null +++ b/doc/concept/Path.md @@ -0,0 +1 @@ +#Paths {#path} \ No newline at end of file diff --git a/doc/concept/SuperNode.md b/doc/concept/SuperNode.md new file mode 100644 index 000000000..147ba0f56 --- /dev/null +++ b/doc/concept/SuperNode.md @@ -0,0 +1 @@ +# Super Nodes {#supernode} \ No newline at end of file diff --git a/doc/figures/states.dia b/doc/figures/states.dia new file mode 100644 index 000000000..91e61a68d Binary files /dev/null and b/doc/figures/states.dia differ diff --git a/doc/nodes/CBuilder.md b/doc/nodes/CBuilder.md index 360c85bd2..ada575c88 100644 --- a/doc/nodes/CBuilder.md +++ b/doc/nodes/CBuilder.md @@ -1,4 +1,4 @@ -# RTDS CBuilder models for VILLASnode +# RTDS CBuilder Control System Components {#cbuilder} RTDS's Component Builder creates user-defined components including graphical representation, data menus and real-time code. diff --git a/doc/nodes/FPGA.md b/doc/nodes/FPGA.md deleted file mode 100644 index 85299e3fb..000000000 --- a/doc/nodes/FPGA.md +++ /dev/null @@ -1,34 +0,0 @@ -# VILLASfpga {#fpga} - -The GTFPGA card is an extension card for simulator racks from RTDS. -The manufacturer provides a VHDL module to exchange data via fiber optics between the GTFPGA and GPC cards. - -The GTFPGA card is based on the Xilinx ML507 or ML605 evaluation boards. -This board consists of a Virtex 5 FPGA, Ethernet and Fiberoptic MACs and an hard macro PowerPC core. - -This node type uses the PCIexpress bus to communicate with the FPGA cards. - -## Configuration - -Every `gtfpga` node support the following special settings: - -#### `slot` - -#### `id` - -#### `rate` - -### Example - - nodes = { - gtfpga_node = { - type = "gtfpga", - - ### The following settings are specific to the gtfpga node-type!! ### - - slot = "01:00.0", # The PCIe slot location (see first column in 'lspci' output) - id = "1ab8:4005", # The PCIe vendor:device ID (see third column in 'lspci -n' output) - - rate = 1 - } - } diff --git a/doc/nodes/File.md b/doc/nodes/File.md index 9b37a6aaa..42839398d 100644 --- a/doc/nodes/File.md +++ b/doc/nodes/File.md @@ -7,9 +7,9 @@ The `file` node-type can be used to log or replay samples to / from disk. Every `file` node can be configured to only read or write or to do both at the same time. The node configuration is splitted in to groups: `in` and `out`. -#### `path` *(string: filesystem path)* +#### `uri` *(string: libcurl URI)* -Specifies the path to a file from which is written to or read from (depending in which group is used). +Specifies the URI to a file from which is written to or read from depending in which group (`in`or `out`) is used. See below for a description of the file format. This setting allows to add special paceholders for time and date values. @@ -17,7 +17,7 @@ See [strftime(3)](http://man7.org/linux/man-pages/man3/strftime.3.html) for a li **Example**: - out = "logs/measurements_%Y-%m-%d_%H-%M-%S.log" + uri = "logs/measurements_%Y-%m-%d_%H-%M-%S.log" will create a file called: *path_of_working_directory*/logs/measurements_2015-08-09_22-20-50.log @@ -29,7 +29,7 @@ Specifies the mode which should be used to open the output file. See [open(2)](http://man7.org/linux/man-pages/man2/open.2.html) for an explanation of allowed values. The default value is `w+` which will start writing at the beginning of the file and create it in case it does not exist yet. -#### `epoch_mode` *("direct"|"wait" | "relative"|"absolute")* +#### `epoch_mode` *("direct" | "wait" | "relative" | "absolute")* The *epoch* describes the point in time when the first message will be read from the file. This setting allows to select the behaviour of the following `epoch` setting. @@ -65,7 +65,7 @@ If this setting has a non-zero value, the default behaviour is overwritten with Only valid for the `out` group. -Splits the output file every `split` mega-byte. This setting will append the chunk number to the `path` setting. +Splits the output file every `split` mega-byte. This setting will append the chunk number to the `uri` setting. Example: `data/my_measurements.log_001` @@ -84,7 +84,7 @@ Expects the input data in splitted format. ### The following settings are specific to the file node-type!! ### in = { - path = "logs/input.log", # These options specify the path prefix where the the files are stored + uri = "logs/input.log", # These options specify the URI where the the files are stored mode = "w+", # The mode in which files should be opened (see open(2)) epoch_mode = "direct" # One of: direct (default), wait, relative, absolute @@ -98,7 +98,7 @@ Expects the input data in splitted format. splitted = false }, out = { - path = "logs/output_%F_%T.log" # The output path accepts all format tokens of (see strftime(3)) + URI = "logs/output_%F_%T.log" # The output URI accepts all format tokens of (see strftime(3)) mode = "a+" # You might want to use "a+" to append to a file split = 100, # Split output file every 100 MB diff --git a/doc/nodes/VILLASfpga.md b/doc/nodes/VILLASfpga.md new file mode 100644 index 000000000..285951c4b --- /dev/null +++ b/doc/nodes/VILLASfpga.md @@ -0,0 +1,63 @@ +# VILLASfpga {#villasfpga} + +__This documentation is outdated!__ + +The GTFPGA card is an extension card for simulator racks from RTDS. +The manufacturer provides a VHDL module to exchange data via fiber optics between the GTFPGA and GPC cards. + +The GTFPGA card is based on the Xilinx ML507 or ML605 evaluation boards. +This board consists of a Virtex 5 FPGA, Ethernet and Fiberoptic MACs and an hard macro PowerPC core. + +This node type uses the PCIexpress bus to communicate with the FPGA cards. + +## Configuration + +Every `fpga` node support the following special settings: + +#### `datamover` + +### Example + + 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; + }, + 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 + } + } + + /* Configure switch_0 */ + paths = ( + { in = "dma_0", out = "rtds_0" }, + { in = "rtds_0", out = "dma_0" } + ) + } + } + + nodes = { + rtds = { + datamover = "dma_0"; + use_irqs = false; + } + } diff --git a/doc/pictures/villas_logo.png b/doc/pictures/villas_logo.png new file mode 100644 index 000000000..390769ab6 Binary files /dev/null and b/doc/pictures/villas_logo.png differ diff --git a/doc/pictures/villas_logo.svg b/doc/pictures/villas_logo.svg new file mode 100644 index 000000000..1932a35c8 --- /dev/null +++ b/doc/pictures/villas_logo.svg @@ -0,0 +1,670 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/theme/header.html b/doc/theme/header.html index 93296f3b6..9ae595d6a 100644 --- a/doc/theme/header.html +++ b/doc/theme/header.html @@ -32,6 +32,9 @@ $(document).ready(function(){ + + + - - - + + + diff --git a/doc/theme/style.css b/doc/theme/style.css index 8f539ea8f..069249785 100644 --- a/doc/theme/style.css +++ b/doc/theme/style.css @@ -3,8 +3,14 @@ } #projectlogo img { - height: 3em; - position: absolute; - right: 0.5em; - top: 0.5em; + height: 3.5em; + margin: 0.25em; +} + +#institutelogo img { + height: 3em; + margin: 0.5em; + position: absolute; + right: 0; + top: 0; } diff --git a/etc/Makefile.inc b/etc/Makefile.inc new file mode 100644 index 000000000..cf2fe8073 --- /dev/null +++ b/etc/Makefile.inc @@ -0,0 +1,8 @@ +etc: + +install-etc: + install -D -t $(DESTDIR)/etc/villas/node etc/*.conf + +clean-etc: + +.PHONY: etc install-etc clean-etc \ No newline at end of file diff --git a/etc/advio.conf b/etc/advio.conf new file mode 100644 index 000000000..5859355fd --- /dev/null +++ b/etc/advio.conf @@ -0,0 +1,24 @@ +/** Test advanced file IO using libcurl. + * + * 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 + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +nodes = { + remote_file = { + type = "file", + out = { + # The output path accepts all format tokens of (see strftime(3)) + uri = "https://1Nrd46fZX8HbggT:badpass@rwth-aachen.sciebo.de/public.php/webdav/node/data/demo_%y-%m-%d_%H-%M-%S.dat", + mode = "a+" # You might want to use "a+" to append to a file + } + in = { + uri = "https://1Nrd46fZX8HbggT:badpass@rwth-aachen.sciebo.de/public.php/webdav/node/data/demo_in.dat", + rate = 1 + } + } +} \ No newline at end of file diff --git a/etc/example.conf b/etc/example.conf index 177537cbe..acab53b2d 100644 --- a/etc/example.conf +++ b/etc/example.conf @@ -1,16 +1,16 @@ -# Example configuration file for VILLASnode -# -# This example includes all valid configuration options for the server. -# Please note, that using all options at the same time does not really -# makes sense. The purpose of this example is to serve as a reference. -# -# 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 -# Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC -## +/** Example configuration file for VILLASnode. + * + * This example includes all valid configuration options for the server. + * Please note, that using all options at the same time does not really + * makes sense. The purpose of this example is to serve as a reference. + * + * 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 + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ # Some global settings are used by multiple configuration files # and therefore defined in separate files @@ -84,7 +84,7 @@ nodes = { ### The following settings are specific to the file node-type!! ### in = { - path = "logs/input.log", # These options specify the path prefix where the the files are stored + uri = "logs/input.log", # These options specify the path prefix where the the files are stored mode = "r", # The mode in which files should be opened (see open(2)) epoch_mode = "direct" # One of: direct (default), wait, relative, absolute @@ -98,7 +98,7 @@ nodes = { splitted = false }, out = { - path = "logs/output_%F_%T.log" # The output path accepts all format tokens of (see strftime(3)) + uri = "logs/output_%F_%T.log" # The output path accepts all format tokens of (see strftime(3)) mode = "a+" # You might want to use "a+" to append to a file split = 100, # Split output file every 100 MB @@ -148,8 +148,6 @@ paths = ( rate = 100, # Send message over this path with a fixed (constant) rate (default: 0). # Setting this value to 0 will disable this feature. - hook = "print", # Register custom hook funktion (see src/hooks.c) - poolsize = 30 # The amount of samples which are kept in a circular buffer. # This number must be larger than the 'vectorize' settings of all # associated input and output nodes! @@ -160,23 +158,31 @@ paths = ( in = "opal_node", # There's only a single source node allowed! out = [ "udp_node", "tcp_node" ], # Multiple destination nodes are supported too. - - hook = [ "print", "decimate:10" ] # Same is true for hooks. - # Multipe hook functions are executed in the order they are specified here. }, { in = "socket_node", out = "file_node", # This path includes all available example hooks. - hook = [ - "ts", # Replace the timestamp of messages with the time of reception - "skip_unchanged:0.1", # Skip messages whose values have not changed more than 0.1 from the previous message. - "skip_first:10", # Skip all messages which have been received in the first 10 seconds - "print", # Print all messages to stdout - "decimate:2", # Only forward every 2nd message - "convert:fixed", # Convert all values to fixed precission. Use 'float' to convert to floating point. - "fir:0" # Apply finite impulse response filter to first value. - # Coefficients are hard-coded in 'include/config.h'. - ] + # A complete list of supported hooks + print = { + output = "stdout" + priority = 0 + }, + ts = { + priority = 1 + } + decimate = { + ratio = 2 # Only forward every 2nd message + }, + convert = { + mode = "fixed" # Convert all values to fixed precission. Use 'float' to convert to floating point. + }, + skip_first = { + seconds = 10 # Skip the first 10 seconds of this path + }, + shift = { + mode = "origin", # Shift origin timestam of samples by +10 seconds + offset = 10 + } } ); diff --git a/etc/fpga-simple.conf b/etc/fpga-simple.conf index 7135b895b..c27d8fbd6 100644 --- a/etc/fpga-simple.conf +++ b/etc/fpga-simple.conf @@ -1,66 +1,58 @@ -# Example configuration file for VILLASnode -# -# This example includes all valid configuration options for the server. -# Please note, that using all options at the same time does not really -# makes sense. The purpose of this example is to serve as a reference. -# -# 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 -# Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC -## +/** Example configuration file for VILLASnode. + * + * 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 + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ # Some global settings are used by multiple configuration files # and therefore defined in separate files @include "global.conf" @include "plugins.conf" -fpga = { - /* 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; - }, - 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 - }, - hls_dft_0 = { - vlnv = "acs.eonerc.rwth-aachen.de:hls:hls_dft:1.0"; - port = 1; - switch = "switch_0"; +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; + }, + 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 + } } + + /* Configure switch_0 */ + paths = ( + { in = "dma_0", out = "rtds_0" }, + { in = "rtds_0", out = "dma_0" } + ) } - - /* Configure switch */ - paths = ( - { in = "dma", out = "hls_dft" }, - { in = "hls_dft", out = "dma" } - ) } nodes = { - dma = { + rtds = { datamover = "dma_0"; use_irqs = false; } - -} \ No newline at end of file +} diff --git a/etc/fpga.conf b/etc/fpga.conf index 43c95eb44..319b64f0f 100644 --- a/etc/fpga.conf +++ b/etc/fpga.conf @@ -1,12 +1,12 @@ -# Example configuration file for VILLASfpga / VILLASnode -# -# 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 -# Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC -## +/** Example configuration file for VILLASfpga / VILLASnode. + * + * 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 + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ # Some global settings are used by multiple configuration files # and therefore defined in separate files diff --git a/etc/global.conf b/etc/global.conf index 163eddb0d..19895c345 100644 --- a/etc/global.conf +++ b/etc/global.conf @@ -1,39 +1,44 @@ -# Global configuration file for VILLASnode -# -# This example includes all valid configuration options for the server. -# Please note, that using all options at the same time does not really -# makes sense. The purpose of this example is to serve as a reference. -# -# 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 -# Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC -## +/** Global configuration file for VILLASnode. + * + * 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 + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ ############ Global Options ############ affinity = 0x01; # Mask of cores the server should run on # This also maps the NIC interrupts to those cores! -#priority = 50; # Priority for the server tasks. +//priority = 50; # Priority for the server tasks. # Usually the server is using a real-time FIFO # scheduling algorithm # See: https://github.com/docker/docker/issues/22380 # on why we cant use real-time scheduling in Docker -debug = 5; # The level of verbosity for debug messages - # Higher number => increased verbosity - stats = 3; # The interval in seconds to print path statistics. # A value of 0 disables the statistics. name = "villas-acs" # The name of this VILLASnode. Might by used by node-types # to identify themselves (default is the hostname). + +log = { + level = 5; # The level of verbosity for debug messages + # Higher number => increased verbosity + + faciltities = [ "path", "socket" ]; # The list of enabled debug faciltities. + # If omitted, all faciltities are enabled + # For a full list of available faciltities, check lib/log.c + + file = "/var/log/villas-node.log"; # File for logs +}; + http = { - htdocs = "/villas/contrib/websocket", # Root directory of internal webserver + htdocs = "/villas/web/socket/", # Root directory of internal webserver port = 80 # Port for HTTP connections } \ No newline at end of file diff --git a/etc/gtnet-skt/test1.conf b/etc/gtnet-skt/test1.conf index 3e5d147b3..93419a814 100644 --- a/etc/gtnet-skt/test1.conf +++ b/etc/gtnet-skt/test1.conf @@ -1,29 +1,12 @@ -# This is an example for a minimal loopback configuration. -# -# All messages will be sent back to the origin using UDP packets. -# -# You can use this configuration in conjunction with the 'send', 'receive' and 'random' -# utilities as shown below (run all three steps in parallel). -# -# 0. Overview: -# -# ./signal --PIPE--> ./pipe --UDP--> ./node --UDP--> ./pipe -# -# 1. Start server: -# -# $ ./node etc/loopback.conf -# -# 2. Send random data to server: -# -# $ ./signal random -r 10 -v 4 | ./pipe etc/loopback.conf node1 -# -# 3. Receive data from server: -# -# $ ./pipe etc/loopback.conf node2 -# -# Author: Steffen Vogel -# Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC -## +/** GTNET-SKT test configuration. + * + * 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 + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ stats = 1; debug = 10; @@ -57,6 +40,10 @@ paths = ( { in = "node1", # Name of the node we listen to (see above) out = "node1", # And we loop back to the origin - hook = ["print"] + + # Hooks + print = { + output = "stdout" + } } ); diff --git a/etc/gtnet-skt/test2.conf b/etc/gtnet-skt/test2.conf index 1c40c3dd4..0cfe1d216 100644 --- a/etc/gtnet-skt/test2.conf +++ b/etc/gtnet-skt/test2.conf @@ -1,29 +1,12 @@ -# This is an example for a minimal loopback configuration. -# -# All messages will be sent back to the origin using UDP packets. -# -# You can use this configuration in conjunction with the 'send', 'receive' and 'random' -# utilities as shown below (run all three steps in parallel). -# -# 0. Overview: -# -# ./signal --PIPE--> ./pipe --UDP--> ./node --UDP--> ./pipe -# -# 1. Start server: -# -# $ ./node etc/loopback.conf -# -# 2. Send random data to server: -# -# $ ./signal random -r 10 -v 4 | ./pipe etc/loopback.conf node1 -# -# 3. Receive data from server: -# -# $ ./pipe etc/loopback.conf node2 -# -# Author: Steffen Vogel -# Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC -## +/** GTNET-SKT test configuration. + * + * 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 + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ stats = 1; debug = 10; @@ -57,6 +40,10 @@ paths = ( { in = "node1", # Name of the node we listen to (see above) out = "node2", # And we loop back to the origin - hook = ["print"] + + # Hooks + print = { + output = "stdout" + } } ); diff --git a/etc/gtnet-skt/test3.conf b/etc/gtnet-skt/test3.conf index 9470160ec..327f7e2e4 100644 --- a/etc/gtnet-skt/test3.conf +++ b/etc/gtnet-skt/test3.conf @@ -1,29 +1,12 @@ -# This is an example for a minimal loopback configuration. -# -# All messages will be sent back to the origin using UDP packets. -# -# You can use this configuration in conjunction with the 'send', 'receive' and 'random' -# utilities as shown below (run all three steps in parallel). -# -# 0. Overview: -# -# ./signal --PIPE--> ./pipe --UDP--> ./node --UDP--> ./pipe -# -# 1. Start server: -# -# $ ./node etc/loopback.conf -# -# 2. Send random data to server: -# -# $ ./signal random -r 10 -v 4 | ./pipe etc/loopback.conf node1 -# -# 3. Receive data from server: -# -# $ ./pipe etc/loopback.conf node2 -# -# Author: Steffen Vogel -# Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC -## +/** GTNET-SKT test configuration. + * + * 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 + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ stats = 1; debug = 10; @@ -57,6 +40,10 @@ paths = ( { in = "node1", # Name of the node we listen to (see above) out = "node2", # And we loop back to the origin - hook = ["print"] + + # Hooks + print = { + output = "stdout" + } } ); diff --git a/etc/gtnet-skt/test4.conf b/etc/gtnet-skt/test4.conf index 4a56ee34d..cfc8a669c 100644 --- a/etc/gtnet-skt/test4.conf +++ b/etc/gtnet-skt/test4.conf @@ -1,29 +1,12 @@ -# This is an example for a minimal loopback configuration. -# -# All messages will be sent back to the origin using UDP packets. -# -# You can use this configuration in conjunction with the 'send', 'receive' and 'random' -# utilities as shown below (run all three steps in parallel). -# -# 0. Overview: -# -# ./signal --PIPE--> ./pipe --UDP--> ./node --UDP--> ./pipe -# -# 1. Start server: -# -# $ ./node etc/loopback.conf -# -# 2. Send random data to server: -# -# $ ./signal random -r 10 -v 4 | ./pipe etc/loopback.conf node1 -# -# 3. Receive data from server: -# -# $ ./pipe etc/loopback.conf node2 -# -# Author: Steffen Vogel -# Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC -## +/** GTNET-SKT test configuration. + * + * 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 + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ stats = 1; debug = 10; @@ -57,6 +40,10 @@ paths = ( { in = "node1", # Name of the node we listen to (see above) out = "node1", # And we loop back to the origin - hook = ["print"] + + # Hooks + print = { + output = "stdout" + } } ); diff --git a/etc/gtnet-skt/test5.conf b/etc/gtnet-skt/test5.conf index a8d9ce9d9..d93549669 100644 --- a/etc/gtnet-skt/test5.conf +++ b/etc/gtnet-skt/test5.conf @@ -1,29 +1,12 @@ -# This is an example for a minimal loopback configuration. -# -# All messages will be sent back to the origin using UDP packets. -# -# You can use this configuration in conjunction with the 'send', 'receive' and 'random' -# utilities as shown below (run all three steps in parallel). -# -# 0. Overview: -# -# ./signal --PIPE--> ./pipe --UDP--> ./node --UDP--> ./pipe -# -# 1. Start server: -# -# $ ./node etc/loopback.conf -# -# 2. Send random data to server: -# -# $ ./signal random -r 10 -v 4 | ./pipe etc/loopback.conf node1 -# -# 3. Receive data from server: -# -# $ ./pipe etc/loopback.conf node2 -# -# Author: Steffen Vogel -# Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC -## +/** GTNET-SKT test configuration. + * + * 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 + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ stats = 1; debug = 10; @@ -58,6 +41,10 @@ paths = ( { in = "node1", # Name of the node we listen to (see above) out = "node1", # And we loop back to the origin - hook = ["print"] + + # Hooks + print = { + output = "stdout" + } } ); diff --git a/etc/loopback.conf b/etc/loopback.conf index adb9538f5..23479abd7 100644 --- a/etc/loopback.conf +++ b/etc/loopback.conf @@ -1,29 +1,33 @@ -# This is an example for a minimal loopback configuration. -# -# All messages will be sent back to the origin using UDP packets. -# -# You can use this configuration in conjunction with the 'send', 'receive' and 'random' -# utilities as shown below (run all three steps in parallel). -# -# 0. Overview: -# -# ./signal --PIPE--> ./pipe --UDP--> ./node --UDP--> ./pipe -# -# 1. Start server: -# -# $ ./node etc/loopback.conf -# -# 2. Send random data to server: -# -# $ ./signal random -r 10 -v 4 | ./pipe etc/loopback.conf node1 -# -# 3. Receive data from server: -# -# $ ./pipe etc/loopback.conf node2 -# -# Author: Steffen Vogel -# Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC -## +/** This is an example for a minimal loopback configuration. + * + * All messages will be sent back to the origin using UDP packets. + * + * You can use this configuration in conjunction with the 'send', 'receive' and 'random' + * utilities as shown below (run all three steps in parallel). + * + * 0. Overview: + * + * ./signal --PIPE--> ./pipe --UDP--> ./node --UDP--> ./pipe + * + * 1. Start server: + * + * $ ./node etc/loopback.conf + * + * 2. Send random data to server: + * + * $ ./signal random -r 10 -v 4 | ./pipe etc/loopback.conf node1 + * + * 3. Receive data from server: + * + * $ ./pipe etc/loopback.conf node2 + * + * 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 + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ stats = 1; debug = 10; @@ -34,15 +38,14 @@ nodes = { layer = "udp", local = "*:12000", # Local ip:port, use '*' for random port remote = "127.0.0.1:12001", - combine = 5, header = "villas", # 'gtnet-skt' or 'villas'. If not provided, 'villas' header will be used - vectorize = 1, # Number of samples to fetch per iteration from the socket netem = { enabled = false, delay = 1000000, # In micro seconds! jitter = 300000, distribution = "normal" } + vectorize = 1 # Number of samples to fetch per iteration from the socket }, node2 = { type = "socket", @@ -58,6 +61,5 @@ paths = ( { in = "node1", # Name of the node we listen to (see above) out = "node2", # And we loop back to the origin - hook = ["decimate:2", "print"] } ); diff --git a/etc/plugins.conf b/etc/plugins.conf index 19f39af92..a2e11729d 100644 --- a/etc/plugins.conf +++ b/etc/plugins.conf @@ -1,16 +1,12 @@ -# Example plugins configuration file for VILLASnode -# -# This example includes all valid configuration options for the server. -# Please note, that using all options at the same time does not really -# makes sense. The purpose of this example is to serve as a reference. -# -# 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 -# Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC -## +/** Example plugins configuration file for VILLASnode. + * + * 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 + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ ############ List of plugins ############ # diff --git a/etc/websocket-stats.conf b/etc/websocket-stats.conf index fdb89bac8..6d29f34e9 100644 --- a/etc/websocket-stats.conf +++ b/etc/websocket-stats.conf @@ -1,10 +1,14 @@ /** This should be included to all websocket node configurations which report * path stats by the 'stats_send' hook. * - * Have a look at etc/ws.conf for an example. + * Have a look at etc/websockets.conf for an example. + * + * 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 - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ series = ( diff --git a/etc/websocket.conf b/etc/websocket.conf index 21e2513b8..e648b18d4 100644 --- a/etc/websocket.conf +++ b/etc/websocket.conf @@ -1,16 +1,12 @@ -# Example configuration file for VILLASnode -# -# This example includes all valid configuration options for the server. -# Please note, that using all options at the same time does not really -# makes sense. The purpose of this example is to serve as a reference. -# -# 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 -# Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC -## +/** Example configuration file for VILLASnode. + * + * 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 + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ # Some global settings are used by multiple configuration files # and therefore defined in separate files @@ -33,7 +29,8 @@ nodes = { series = ( { label = "Random walk" }, { label = "Sine" }, - { label = "Rect" } + { label = "Rect" }, + { label = "Ramp" } ) } }; diff --git a/include/villas/advio.h b/include/villas/advio.h new file mode 100644 index 000000000..c4ca19a25 --- /dev/null +++ b/include/villas/advio.h @@ -0,0 +1,44 @@ +/** libcurl based advanced IO aka ADVIO. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#pragma once + +#include + +#include + +#include "utils.h" + +struct advio { + CURL *curl; + FILE *file; + + unsigned char hash[SHA_DIGEST_LENGTH]; + + char mode[2]; + char *uri; +}; + +typedef struct advio AFILE; + +/* The remaining functions from stdio are just replaced macros */ +#define afeof(af) feof((af)->file) +#define aftell(af) ftell((af)->file) +#define arewind(af) rewind((af)->file) +#define afileno(af) fileno((af)->file) +#define afread(ptr, sz, nitems, af) fread(ptr, sz, nitems, (af)->file) +#define afwrite(ptr, sz, nitems, af) fwrite(ptr, sz, nitems, (af)->file) + +/* Extensions */ +#define auri(af) ((af)->uri) +#define ahash(af) ((af)->hash) + +AFILE *afopen(const char *url, const char *mode); + +int afclose(AFILE *file); +int afflush(AFILE *file); +int adownload(AFILE *af); +int aupload(AFILE *af); diff --git a/include/villas/api.h b/include/villas/api.h new file mode 100644 index 000000000..35dfcd307 --- /dev/null +++ b/include/villas/api.h @@ -0,0 +1,114 @@ +/** REST-API-releated functions. + * + * @file + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#pragma once + +#include + +#include "list.h" +#include "common.h" + +/* Forward declarations */ +enum lws_callback_reasons; +struct lws; +struct super_node; + +struct api; +struct api_ressource; +struct api_buffer; +struct api_session; + +/** Callback type of command function + * + * @param[inout] c Command handle + * @param[in] args JSON command arguments. + * @param[out] resp JSON command response. + * @param[in] i Execution context. + */ +typedef int (*api_cb_t)(struct api_ressource *c, json_t *args, json_t **resp, struct api_session *s); + +enum api_version { + API_VERSION_UNKOWN = 0, + API_VERSION_1 = 1 +}; + +enum api_mode { + API_MODE_WS, /**< This API session was established over a WebSocket connection. */ + API_MODE_HTTP /**< This API session was established via a HTTP REST request. */ +}; + +struct api { + struct list sessions; /**< List of currently active connections */ + + enum state state; + + struct super_node *super_node; +}; + +struct api_buffer { + char *buf; /**< A pointer to the buffer. Usually resized via realloc() */ + size_t size; /**< The allocated size of the buffer. */ + size_t len; /**< The used length of the buffer. */ +}; + +/** A connection via HTTP REST or WebSockets to issue API actions. */ +struct api_session { + enum api_mode mode; + enum api_version version; + + int runs; + + struct { + struct api_buffer body; /**< HTTP body / WS payload */ + } request; + + struct { + struct api_buffer body; /**< HTTP body / WS payload */ + struct api_buffer headers; /**< HTTP headers */ + } response; + + bool completed; /**< Did we receive the complete body yet? */ + + struct api *api; +}; + +/** Command descriptor + * + * Every command is described by a descriptor. + */ +struct api_ressource { + api_cb_t cb; +}; + +/** Initalize the API. + * + * Save references to list of paths / nodes for command execution. + */ +int api_init(struct api *a, struct super_node *sn); + +int api_destroy(struct api *a); + +int api_start(struct api *a); + +int api_stop(struct api *a); + +int api_session_init(struct api_session *s, struct api *a, enum api_mode m); + +int api_session_destroy(struct api_session *s); + +int api_session_run_command(struct api_session *s, json_t *req, json_t **resp); + +/** Send contents of buffer over libwebsockets connection */ +int api_buffer_send(struct api_buffer *b, struct lws *w); + +/** Append received data to buffer. */ +int api_buffer_append(struct api_buffer *b, const char *in, size_t len); + +/** Libwebsockets callback for "api" endpoint */ +int api_ws_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); + +int api_http_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); \ No newline at end of file diff --git a/include/villas/cfg.h b/include/villas/cfg.h deleted file mode 100644 index d7f871fc7..000000000 --- a/include/villas/cfg.h +++ /dev/null @@ -1,109 +0,0 @@ -/** Configuration file parser. - * - * The server program is configured by a single file. - * This config file is parsed with a third-party library: - * libconfig http://www.hyperrealm.com/libconfig/ - * - * @file - * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC - *********************************************************************************/ - -#ifndef _CFG_H_ -#define _CFG_H_ - -#include - -/* Forward declarations */ -struct list; -struct settings; - -/* Compatibility with libconfig < 1.5 */ -#if (LIBCONFIG_VER_MAJOR <= 1) && (LIBCONFIG_VER_MINOR < 5) - #define config_setting_lookup config_lookup_from -#endif - -/** Simple wrapper around libconfig's config_init() - * - * This allows us to avoid an additional library dependency to libconfig - * for the excuctables. They only have to depend on libvillas. - */ -void cfg_init(config_t *cfg); - -/** Simple wrapper around libconfig's config_init() */ -void cfg_destroy(config_t *cfg); - -/** Parse config file and store settings in supplied struct settings. - * - * @param filename The path to the configration file (relative or absolute) - * @param cfg A initialized libconfig object - * @param set The global configuration structure - * @param nodes A linked list of nodes which should be parsed - * @param paths A linked list of paths which should be parsed - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ -int cfg_parse(const char *filename, config_t *cfg, struct settings *set, - struct list *nodes, struct list *paths); - -/** Parse the global section of a configuration file. - * - * @param cfg A libconfig object pointing to the root of the file - * @param set The global configuration file - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ -int cfg_parse_global(config_setting_t *cfg, struct settings *set); - -/** Parse a single path and add it to the global configuration. - * - * @param cfg A libconfig object pointing to the path - * @param paths Add new paths to this linked list - * @param nodes A linked list of all existing nodes - * @param set The global configuration structure - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ -int cfg_parse_path(config_setting_t *cfg, - struct list *paths, struct list *nodes, struct settings *set); - -/** Parse an array or single node and checks if they exist in the "nodes" section. - * - * Examples: - * out = [ "sintef", "scedu" ] - * out = "acs" - * - * @param cfg The libconfig object handle for "out". - * @param nodes The nodes will be added to this list. - * @param all This list contains all valid nodes. - */ -int cfg_parse_nodelist(config_setting_t *cfg, struct list *nodes, struct list *all); - -/** Parse an array or single hook function. - * - * Examples: - * hooks = [ "print", "fir" ] - * hooks = "log" - **/ -int cfg_parse_hooklist(config_setting_t *cfg, struct list *hooks); - -/** Parse a single hook and append it to the list. - * A hook definition is composed of the hook name and optional parameters - * seperated by a colon. - * - * Examples: - * "print:stdout" - */ -int cfg_parse_hook(config_setting_t *cfg, struct list *list); - -/** Parse a single node and add it to the global configuration. - * - * @param cfg A libconfig object pointing to the node. - * @param nodes Add new nodes to this linked list. - * @param set The global configuration structure - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ -int cfg_parse_node(config_setting_t *cfg, struct list *nodes, struct settings *set); - -#endif /* _CFG_H_ */ diff --git a/include/villas/common.h b/include/villas/common.h new file mode 100644 index 000000000..d1f3a210e --- /dev/null +++ b/include/villas/common.h @@ -0,0 +1,20 @@ +/** Some common defines, enums and datastructures. + * + * @file + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#pragma once + +/* Common states for most objects in VILLASnode (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 */ +}; \ No newline at end of file diff --git a/include/villas/fpga/card.h b/include/villas/fpga/card.h new file mode 100644 index 000000000..7b2396d3f --- /dev/null +++ b/include/villas/fpga/card.h @@ -0,0 +1,65 @@ +/** FPGA card + * + * This class represents a FPGA device. + * + * @file + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +/** @addtogroup fpga VILLASfpga + * @{ + */ + +#pragma once + +#include + +#include "common.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_device filter; /**< Filter for PCI device. */ + 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; + + config_setting_t *cfg; +}; + +int fpga_card_parse(struct fpga_card *c, config_setting_t *cfg); + +void fpga_card_dump(struct fpga_card *c); + +/** Initialize FPGA card and its IP components. */ +int fpga_card_init(struct fpga_card *c, struct pci *pci, struct vfio_container *vc); + +int fpga_card_destroy(struct fpga_card *c); + +/** Check if the FPGA card configuration is plausible. */ +int fpga_card_check(struct fpga_card *c); + +/** Reset the FPGA to a known state */ +int fpga_card_reset(struct fpga_card *c); + +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/dma.h b/include/villas/fpga/dma.h deleted file mode 100644 index 7b2eb45e5..000000000 --- a/include/villas/fpga/dma.h +++ /dev/null @@ -1,66 +0,0 @@ -/** DMA related helper functions - * - * These functions present a simpler interface to Xilinx' DMA driver (XAxiDma_*) - * - * @file - * @author Steffen Vogel - * @copyright 2016, Steffen Vogel - **********************************************************************************/ - -#ifndef _DMA_H_ -#define _DMA_H_ - -#include -#include -#include - -#include - -#define FPGA_DMA_BASEADDR 0x00000000 -#define FPGA_DMA_BOUNDARY 0x1000 -#define FPGA_DMA_BD_OFFSET 0xC0000000 -#define FPGA_DMA_BD_SIZE (32 << 20) // 32 MB - -#define XAXIDMA_SR_SGINCL_MASK 0x00000008 - -struct dma_mem { - char *base_virt; - char *base_phys; - size_t len; -}; - -struct dma { - XAxiDma inst; - - struct dma_mem bd; -}; - -struct ip; - -int dma_mem_split(struct dma_mem *o, struct dma_mem *a, struct dma_mem *b); - -int dma_alloc(struct ip *c, struct dma_mem *mem, size_t len, int flags); -int dma_free(struct ip *c, struct dma_mem *mem); - -int dma_write(struct ip *c, char *buf, size_t len); -int dma_read(struct ip *c, char *buf, size_t len); -int dma_read_complete(struct ip *c, char **buf, size_t *len); -int dma_write_complete(struct ip *c, char **buf, size_t *len); - -int dma_sg_write(struct ip *c, char *buf, size_t len); -int dma_sg_read(struct ip *c, char *buf, size_t len); - -int dma_sg_write_complete(struct ip *c, char **buf, size_t *len); -int dma_sg_read_complete(struct ip *c, char **buf, size_t *len); - -int dma_simple_read(struct ip *c, char *buf, size_t len); -int dma_simple_write(struct ip *c, char *buf, size_t len); - -int dma_simple_read_complete(struct ip *c, char **buf, size_t *len); -int dma_simple_write_complete(struct ip *c, char **buf, size_t *len); - -int dma_ping_pong(struct ip *c, char *src, char *dst, size_t len); - -int dma_init(struct ip *c); - -#endif /* _DMA_H_ */ \ No newline at end of file diff --git a/include/villas/fpga/ip.h b/include/villas/fpga/ip.h index a573709c1..5d0948bd1 100644 --- a/include/villas/fpga/ip.h +++ b/include/villas/fpga/ip.h @@ -1,101 +1,107 @@ -#ifndef _IP_H_ -#define _IP_H_ +/** Interlectual Property component. + * + * This class represents a module within the FPGA. + * + * @file + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +/** @addtogroup fpga VILLASfpga + * @{ + */ + +#pragma once #include -#include -#include -#include -#include -#include +#include "common.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" -#define REGISTER_IP_TYPE(ip) \ -__attribute__((constructor)) static \ -void UNIQUE(__register_)() { \ - list_push(&ip_types, ip); \ -} +#include "fpga/vlnv.h" -extern struct list ip_types; /**< Table of existing FPGA IP core drivers */ +#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 ip_state { - IP_STATE_UNKNOWN, - IP_STATE_INITIALIZED -}; +enum fpga_ip_types { + FPGA_IP_TYPE_DM_DMA, /**< A datamover IP exchanges streaming data between the FPGA and the CPU. */ + FPGA_IP_TYPE_DM_FIFO, /**< 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; -struct ip_vlnv { - char *vendor; - char *library; - char *name; - char *version; -}; +struct fpga_ip_type { + struct fpga_vlnv vlnv; -struct ip_type { - struct ip_vlnv vlnv; + enum fpga_ip_types type; - 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); -}; - -struct ip { - char *name; - - struct ip_vlnv vlnv; - - uintptr_t baseaddr; - uintptr_t baseaddr_axi4; - - int port, irq; - - enum ip_state state; - - struct ip_type *_vt; - - union { - struct model model; - struct timer timer; - struct fifo fifo; - struct dma dma; - struct sw sw; - struct dft dft; - struct intc intc; - }; + int (*init)(struct fpga_ip *c); + int (*parse)(struct fpga_ip *c); + int (*check)(struct fpga_ip *c); + int (*start)(struct fpga_ip *c); + int (*stop)(struct fpga_ip *c); + int (*destroy)(struct fpga_ip *c); + int (*reset)(struct fpga_ip *c); + void (*dump)(struct fpga_ip *c); - struct fpga *card; + size_t size; /**< Amount of memory which should be reserved for struct fpga_ip::_vd */ +}; + +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. */ + + enum state state; /**< The current state of the FPGA IP component. */ + + struct fpga_ip_type *_vt; /**< Vtable containing FPGA IP type function pointers. */ + void *_vd; /**< Virtual data (used by struct fpga_ip::_vt functions) */ + + uintptr_t baseaddr; /**< The baseadress of this FPGA IP component */ + uintptr_t baseaddr_axi4; /**< Used by AXI4 FIFO DM */ + + 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. */ + + 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 core. */ +int fpga_ip_init(struct fpga_ip *c, struct fpga_ip_type *vt); -/** Check if IP block \p c matched VLNV. */ -int ip_vlnv_match(struct ip *c, const char *vendor, const char *library, const char *name, const char *version); +/** Parse IP core configuration from configuration file */ +int fpga_ip_parse(struct fpga_ip *c, config_setting_t *cfg); -/** Tokenizes VLNV \p vlnv and stores it into \p c */ -int ip_vlnv_parse(struct ip *c, const char *vlnv); +/** Check configuration of IP core. */ +int fpga_ip_check(struct fpga_ip *c); -int ip_init(struct ip *c); +/** Start IP core. */ +int fpga_ip_start(struct fpga_ip *c); -void ip_destroy(struct ip *c); +/** Stop IP core. */ +int fpga_ip_stop(struct fpga_ip *c); -void ip_dump(struct ip *c); +/** Release dynamic memory allocated by this IP core. */ +int fpga_ip_destroy(struct fpga_ip *c); -int ip_reset(struct ip *c); +/** Dump details about this IP core to stdout. */ +void fpga_ip_dump(struct fpga_ip *c); -int ip_parse(struct ip *c, config_setting_t *cfg); +/** Reset IP component to its initial state. */ +int fpga_ip_reset(struct fpga_ip *c); -#endif \ No newline at end of file +/** Find a registered FPGA IP core type with the given VLNV identifier. */ +struct fpga_ip_type * fpga_ip_type_lookup(const char *vstr); + + +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/dft.h b/include/villas/fpga/ips/dft.h similarity index 53% rename from include/villas/fpga/dft.h rename to include/villas/fpga/ips/dft.h index a908ebd2b..ca7d16b0f 100644 --- a/include/villas/fpga/dft.h +++ b/include/villas/fpga/ips/dft.h @@ -2,11 +2,14 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Steffen Vogel - **********************************************************************************/ - -#ifndef _DFT_H_ -#define _DFT_H_ + * @copyright 2017, Steffen Vogel +**********************************************************************************/ + +/** @addtogroup fpga VILLASfpga + * @{ + */ + +#pragma once #include @@ -22,11 +25,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 /* _DFT_H_ */ \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/ips/dma.h b/include/villas/fpga/ips/dma.h new file mode 100644 index 000000000..db05a9595 --- /dev/null +++ b/include/villas/fpga/ips/dma.h @@ -0,0 +1,72 @@ +/** DMA related helper functions. + * + * These functions present a simpler interface to Xilinx' DMA driver (XAxiDma_*). + * + * @file + * @author Steffen Vogel + * @copyright 2017, Steffen Vogel + **********************************************************************************/ + +/** @addtogroup fpga VILLASfpga + * @{ + */ + +#pragma once + +#include +#include +#include + +#include + +/* Forward declarations */ +struct fpga_ip; + +#define FPGA_DMA_BASEADDR 0x00000000 +#define FPGA_DMA_BOUNDARY 0x1000 +#define FPGA_DMA_BD_OFFSET 0xC0000000 +#define FPGA_DMA_BD_SIZE (32 << 20) // 32 MB + +#define XAXIDMA_SR_SGINCL_MASK 0x00000008 + +struct dma_mem { + char *base_virt; + char *base_phys; + size_t len; +}; + +struct dma { + XAxiDma inst; + + struct dma_mem bd; +}; + +struct ip; + +int dma_mem_split(struct dma_mem *o, struct dma_mem *a, struct dma_mem *b); + +int dma_alloc(struct fpga_ip *c, struct dma_mem *mem, size_t len, int flags); +int dma_free(struct fpga_ip *c, struct dma_mem *mem); + +int dma_write(struct fpga_ip *c, char *buf, size_t len); +int dma_read(struct fpga_ip *c, char *buf, size_t len); +int dma_read_complete(struct fpga_ip *c, char **buf, size_t *len); +int dma_write_complete(struct fpga_ip *c, char **buf, size_t *len); + +int dma_sg_write(struct fpga_ip *c, char *buf, size_t len); +int dma_sg_read(struct fpga_ip *c, char *buf, size_t len); + +int dma_sg_write_complete(struct fpga_ip *c, char **buf, size_t *len); +int dma_sg_read_complete(struct fpga_ip *c, char **buf, size_t *len); + +int dma_simple_read(struct fpga_ip *c, char *buf, size_t len); +int dma_simple_write(struct fpga_ip *c, char *buf, size_t len); + +int dma_simple_read_complete(struct fpga_ip *c, char **buf, size_t *len); +int dma_simple_write_complete(struct fpga_ip *c, char **buf, size_t *len); + +int dma_ping_pong(struct fpga_ip *c, char *src, char *dst, size_t len); + +int dma_init(struct fpga_ip *c); + +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/fifo.h b/include/villas/fpga/ips/fifo.h similarity index 64% rename from include/villas/fpga/fifo.h rename to include/villas/fpga/ips/fifo.h index 1b66d32fa..d685fd663 100644 --- a/include/villas/fpga/fifo.h +++ b/include/villas/fpga/ips/fifo.h @@ -4,11 +4,14 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel **********************************************************************************/ -#ifndef _FIFO_H_ -#define _FIFO_H_ +/** @addtogroup fpga VILLASfpga + * @{ + */ + +#pragma once #include @@ -24,10 +27,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 /* _FIFO_H_ */ \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/intc.h b/include/villas/fpga/ips/intc.h similarity index 60% rename from include/villas/fpga/intc.h rename to include/villas/fpga/ips/intc.h index cc3395ab8..b4898730b 100644 --- a/include/villas/fpga/intc.h +++ b/include/villas/fpga/ips/intc.h @@ -1,11 +1,14 @@ /** AXI-PCIe Interrupt controller * * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel **********************************************************************************/ -#ifndef _INTC_H_ -#define _INTC_H_ +/** @addtogroup fpga VILLASfpga + * @{ + */ + +#pragma once #include @@ -23,14 +26,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 /* _INTC_H_ */ \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/model.h b/include/villas/fpga/ips/model.h similarity index 82% rename from include/villas/fpga/model.h rename to include/villas/fpga/ips/model.h index a985f8f94..aa191ea00 100644 --- a/include/villas/fpga/model.h +++ b/include/villas/fpga/ips/model.h @@ -2,11 +2,14 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel *********************************************************************************/ - -#ifndef _MODEL_H_ -#define _MODEL_H_ + +/** @addtogroup fpga VILLASfpga + * @{ + */ + +#pragma once #include #include @@ -83,26 +86,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. * @@ -121,4 +124,4 @@ int model_param_write(struct model_param *p, double v); int model_param_update(struct model_param *p, struct model_param *u); -#endif /* _MODEL_H_ */ \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/rtds_axis.h b/include/villas/fpga/ips/rtds_axis.h similarity index 90% rename from include/villas/fpga/rtds_axis.h rename to include/villas/fpga/ips/rtds_axis.h index 86f0e9168..f48fd8390 100644 --- a/include/villas/fpga/rtds_axis.h +++ b/include/villas/fpga/ips/rtds_axis.h @@ -2,13 +2,16 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel **********************************************************************************/ -#ifndef _RTDS_AXIS_H_ -#define _RTDS_AXIS_H_ +/** @addtogroup fpga VILLASfpga + * @{ + */ -/* Forward declaration */ +#pragma once + +/* Forward declarations */ struct ip; #define RTDS_HZ 100000000 // 100 MHz @@ -36,8 +39,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 /* _RTDS_AXIS_H_ */ \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/switch.h b/include/villas/fpga/ips/switch.h similarity index 59% rename from include/villas/fpga/switch.h rename to include/villas/fpga/ips/switch.h index 8c299ad59..1172ab9cb 100644 --- a/include/villas/fpga/switch.h +++ b/include/villas/fpga/ips/switch.h @@ -4,11 +4,14 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel **********************************************************************************/ -#ifndef _SWITCH_H_ -#define _SWITCH_H_ +/** @addtogroup fpga VILLASfpga + * @{ + */ + +#pragma once #include @@ -31,17 +34,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 /* _SWITCH_H_ */ \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/timer.h b/include/villas/fpga/ips/timer.h similarity index 71% rename from include/villas/fpga/timer.h rename to include/villas/fpga/ips/timer.h index 39e73f5ff..f1ae91ecb 100644 --- a/include/villas/fpga/timer.h +++ b/include/villas/fpga/ips/timer.h @@ -4,14 +4,19 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel **********************************************************************************/ -#ifndef _TIMER_H_ -#define _TIMER_H_ +/** @addtogroup fpga VILLASfpga + * @{ + */ + +#pragma once + +#include struct timer { XTmrCtr inst; }; -#endif \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/vlnv.h b/include/villas/fpga/vlnv.h new file mode 100644 index 000000000..cf03226ee --- /dev/null +++ b/include/villas/fpga/vlnv.h @@ -0,0 +1,37 @@ +/** Vendor, Library, Name, Version (VLNV) tag. + * + * @file + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +/** @addtogroup fpga VILLASfpga + * @{ + */ + +#ifndef _FPGA_VLNV_H_ +#define _FPGA_VLNV_H_ + +/* Forward declarations */ +struct list; + +struct fpga_vlnv { + char *vendor; + char *library; + char *name; + char *version; +}; + +/** Return the first IP block in list \p l which matches the VLNV */ +struct fpga_ip * fpga_vlnv_lookup(struct list *l, struct fpga_vlnv *v); + +/** Check if IP block \p c matched VLNV. */ +int fpga_vlnv_cmp(struct fpga_vlnv *a, struct fpga_vlnv *b); + +/** Tokenizes VLNV \p vlnv and stores it into \p c */ +int fpga_vlnv_parse(struct fpga_vlnv *c, const char *vlnv); + +/** Release memory allocated by fpga_vlnv_parse(). */ +int fpga_vlnv_destroy(struct fpga_vlnv *v); + +#endif /** _FPGA_VLNV_H_ @} */ \ No newline at end of file diff --git a/include/villas/hist.h b/include/villas/hist.h index 31d2b8d3e..f56476abc 100644 --- a/include/villas/hist.h +++ b/include/villas/hist.h @@ -2,20 +2,22 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ -#ifndef _HIST_H_ -#define _HIST_H_ +#pragma once #include +#include + +#include #include "config.h" #define HIST_HEIGHT (LOG_WIDTH - 55) #define HIST_SEQ 17 -typedef unsigned hist_cnt_t; +typedef uintmax_t hist_cnt_t; /** Histogram structure used to collect statistics. */ struct hist { @@ -40,10 +42,10 @@ struct hist { }; /** Initialize struct hist with supplied values and allocate memory for buckets. */ -void hist_create(struct hist *h, double start, double end, double resolution); +int hist_init(struct hist *h, double start, double end, double resolution); /** Free the dynamically allocated memory. */ -void hist_destroy(struct hist *h); +int hist_destroy(struct hist *h); /** Reset all counters and values back to zero. */ void hist_reset(struct hist *h); @@ -61,7 +63,7 @@ double hist_mean(struct hist *h); double hist_stddev(struct hist *h); /** Print all statistical properties of distribution including a graphilcal plot of the histogram. */ -void hist_print(struct hist *h); +void hist_print(struct hist *h, int details); /** Print ASCII style plot of histogram */ void hist_plot(struct hist *h); @@ -73,6 +75,8 @@ void hist_plot(struct hist *h); char * hist_dump(struct hist *h); /** Prints Matlab struct containing all infos to file. */ -void hist_matlab(struct hist *h, FILE *f); +int hist_dump_matlab(struct hist *h, FILE *f); -#endif /* _HIST_H_ */ +int hist_dump_json(struct hist *h, FILE *f); + +json_t * hist_json(struct hist *h); diff --git a/include/villas/hook.h b/include/villas/hook.h new file mode 100644 index 000000000..3835069d9 --- /dev/null +++ b/include/villas/hook.h @@ -0,0 +1,114 @@ +/** Hook funktions + * + * Every path can register a hook function which is called for every received + * message. This can be used to debug the data flow, get statistics + * or alter the message. + * + * This file includes some examples. + * + * @file + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + */ +/** + * @addtogroup hooks User-defined hook functions + * @ingroup path + * @{ + *********************************************************************************/ + +#pragma once + +#include +#include +#include + +#include "queue.h" +#include "list.h" +#include "super_node.h" +#include "common.h" + +/* Forward declarations */ +struct path; +struct hook; +struct sample; +struct super_node; + +struct hook_type { + int priority; /**< Default priority of this hook type. */ + bool builtin; /**< Should we add this hook by default to every path?. */ + + size_t size; /**< Size of allocation for struct hook::_vd */ + + int (*parse)(struct hook *h, config_setting_t *cfg); + + int (*init)(struct hook *h); /**< Called before path is started to parseHOOK_DESTROYs. */ + int (*destroy)(struct hook *h); /**< Called after path has been stopped to release memory allocated by HOOK_INIT */ + + int (*start)(struct hook *h); /**< Called whenever a path is started; before threads are created. */ + int (*stop)(struct hook *h); /**< Called whenever a path is stopped; after threads are destoyed. */ + + int (*periodic)(struct hook *h);/**< Called periodically. Period is set by global 'stats' option in the configuration file. */ + int (*restart)(struct hook *h); /**< Called whenever a new simulation case is started. This is detected by a sequence no equal to zero. */ + + int (*read)(struct hook *h, struct sample *smps[], size_t *cnt); /**< Called for every single received samples. */ + int (*write)(struct hook *h, struct sample *smps[], size_t *cnt); /**< Called for every single sample which will be sent. */ +}; + +/** Descriptor for user defined hooks. See hooks[]. */ +struct hook { + enum state state; + + struct sample *prev, *last; + struct path *path; + + struct hook_type *_vt; /**< C++ like Vtable pointer. */ + void *_vd; /**< Private data for this hook. This pointer can be used to pass data between consecutive calls of the callback. */ + + int priority; /**< A priority to change the order of execution within one type of hook. */ +}; + +/** Save references to global nodes, paths and settings */ +int hook_init(struct hook *h, struct hook_type *vt, struct path *p); + +/** Parse a single hook. + * + * A hook definition is composed of the hook name and optional parameters + * seperated by a colon. + * + * Examples: + * "print:stdout" + */ +int hook_parse(struct hook *h, config_setting_t *cfg); + +int hook_destroy(struct hook *h); + +int hook_start(struct hook *h); +int hook_stop(struct hook *h); + +int hook_periodic(struct hook *h); +int hook_restart(struct hook *h); + +int hook_read(struct hook *h, struct sample *smps[], size_t *cnt); +int hook_write(struct hook *h, struct sample *smps[], size_t *cnt); + +size_t hook_read_list(struct list *hs, struct sample *smps[], size_t cnt); +size_t hook_write_list(struct list *hs, struct sample *smps[], size_t cnt); + +/** Compare two hook functions with their priority. Used by list_sort() */ +int hook_cmp_priority(const void *a, const void *b); + +/** Parses an object of hooks + * + * Example: + * + * { + * stats = { + * output = "stdout" + * }, + * skip_first = { + * seconds = 10 + * }, + * hooks = [ "print" ] + * } + */ +int hook_parse_list(struct list *list, config_setting_t *cfg, struct path *p); \ No newline at end of file diff --git a/include/villas/hooks.h b/include/villas/hooks.h deleted file mode 100644 index 55f741450..000000000 --- a/include/villas/hooks.h +++ /dev/null @@ -1,155 +0,0 @@ -/** Hook funktions - * - * Every path can register a hook function which is called for every received - * message. This can be used to debug the data flow, get statistics - * or alter the message. - * - * This file includes some examples. - * - * @file - * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC - */ -/** - * @addtogroup hooks User-defined hook functions - * @ingroup path - * @{ - *********************************************************************************/ - -#ifndef _HOOKS_H_ -#define _HOOKS_H_ - -#include -#include - -#include "queue.h" -#include "list.h" - -#define REGISTER_HOOK(nam, desc, prio, hist, fnc, typ) \ -__attribute__((constructor)) void __register_ ## fnc () { \ - static struct hook h = { \ - .name = nam, \ - .description = desc, \ - .priority = prio, \ - .history = hist, \ - .type = typ, \ - .cb = fnc \ - }; \ - list_push(&hooks, &h); \ -} - -/* The configuration of hook parameters is done in "config.h" */ - -/* Forward declarations */ -struct path; -struct hook; -struct sample; -struct settings; - -/** This is a list of hooks which can be used in the configuration file. */ -extern struct list hooks; - -/** Callback type of hook function - * - * @param p The path which is processing this message. - * @param h The hook datastructure which contains parameter, name and private context for the hook. - * @param m A pointer to the first message which should be processed by the hook. - * @param cnt The number of messages which should be processed by the hook. - * @param when Provides the type of hook for which this occurence of the callback function was executed. See hook_type for possible values. - * @retval 0 Success. Continue processing and forwarding the message. - * @retval <0 Error. Drop the message. - */ -typedef int (*hook_cb_t)(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt); - -/** The type of a hook defines when a hook will be exectuted. This is used as a bitmask. */ -enum hook_type { - HOOK_PATH_START = 1 << 0, /**< Called whenever a path is started; before threads are created. */ - HOOK_PATH_STOP = 1 << 1, /**< Called whenever a path is stopped; after threads are destoyed. */ - HOOK_PATH_RESTART = 1 << 2, /**< Called whenever a new simulation case is started. This is detected by a sequence no equal to zero. */ - - HOOK_READ = 1 << 3, /**< Called for every single received samples. */ - HOOK_WRITE = 1 << 4, /**< Called for every single sample which will be sent. */ - - HOOK_ASYNC = 1 << 7, /**< Called asynchronously with fixed rate (see path::rate). */ - HOOK_PERIODIC = 1 << 8, /**< Called periodically. Period is set by global 'stats' option in the configuration file. */ - - HOOK_INIT = 1 << 9, /**< Called before path is started to parse parameters. */ - HOOK_DEINIT = 1 << 10, /**< Called after path has been stopped to release memory allocated by HOOK_INIT */ - - HOOK_INTERNAL = 1 << 11, /**< Internal hooks are added to every path implicitely. */ - HOOK_PARSE = 1 << 12, /**< Called for parsing hook arguments. */ - - /** @{ Classes of hooks */ - /** Hooks which are using private data must allocate and free them propery. */ - HOOK_STORAGE = HOOK_INIT | HOOK_DEINIT, - /** All path related actions */ - HOOK_PATH = HOOK_PATH_START | HOOK_PATH_STOP | HOOK_PATH_RESTART, - /** Hooks which are used to collect statistics. */ - HOOK_STATS = HOOK_INTERNAL | HOOK_STORAGE | HOOK_PATH | HOOK_READ | HOOK_PERIODIC, - - /** All hooks */ - HOOK_ALL = HOOK_INTERNAL - 1 - /** @} */ -}; - -/** Descriptor for user defined hooks. See hooks[]. */ -struct hook { - const char *name; /**< The unique name of this hook. This must be the first member! */ - const char *parameter; /**< A parameter string for this hook. Can be used to configure the hook behaviour. */ - const char *description;/**< A short description of this hook function. */ - - int priority; /**< A priority to change the order of execution within one type of hook */ - int history; /**< How many samples of history this hook requires. */ - enum hook_type type; /**< The type of the hook as a bitfield */ - - void *_vd; /**< Private data for this hook. This pointer can be used to pass data between consecutive calls of the callback. */ - - struct sample *last; - struct sample *prev; - - hook_cb_t cb; /**< The hook callback function as a function pointer. */ -}; - -/** Save references to global nodes, paths and settings */ -void hook_init(struct list *nodes, struct list *paths, struct settings *set); - -/** Sort hook list according to the their priority. See hook::priority. */ -int hooks_sort_priority(const void *a, const void *b); - -/** Conditionally execute the hooks - * - * @param p A pointer to the path structure. - * @param when Which type of hooks should be executed? - * @param m An array to of (cnt) pointers to msgs. - * @param cnt The size of the message array. - * @retval 0 All registred hooks for the specified type have been executed successfully. - * @retval <0 On of the hook functions signalized, that the processing should be aborted; message should be skipped. - */ -int hook_run(struct path *p, struct sample *smps[], size_t cnt, int when); - -/** Allocate & deallocate private memory per hook. - * - * Hooks which use this function must be flagged with HOOL_STORAGE. - * - * @param h A pointer to the hook structure. - * @param when Which event cause the hook to be executed? - * @param len The size of hook prvate memory allocation. - * @return A pointer to the allocated memory region or NULL after it was released. - */ -void * hook_storage(struct hook *h, int when, size_t len); - -int hook_print(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt); -int hook_ts(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt); -int hook_convert(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt); -int hook_decimate(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt); -int hook_skip_first(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt); - -int hook_stats_send(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt); -int hook_stats(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt); -void hook_stats_header(); - -int hook_fix_ts(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt); -int hook_restart(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt); -int hook_drop(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt); - -#endif /** _HOOKS_H_ @} */ diff --git a/include/villas/kernel/if.h b/include/villas/kernel/if.h index 2aba6c3c5..5df083efb 100644 --- a/include/villas/kernel/if.h +++ b/include/villas/kernel/if.h @@ -5,11 +5,12 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ -#ifndef _IF_H_ -#define _IF_H_ +/** @addtogroup fpga Kernel @{ */ + +#pragma once #include #include @@ -42,14 +43,14 @@ struct interface { * @retval >0 Success. A pointer to the new interface. * @retval 0 Error. The creation failed. */ -struct interface * if_create(struct rtnl_link *link); +int if_init(struct interface * , struct rtnl_link *link); /** Destroy interface by freeing dynamically allocated memory. * * @param i A pointer to the interface structure. */ -void if_destroy(struct interface *i); +int if_destroy(struct interface *i); /** Start interface. * @@ -104,4 +105,4 @@ int if_get_irqs(struct interface *i); */ int if_set_affinity(struct interface *i, int affinity); -#endif /* _IF_H_ */ +/** @} */ \ No newline at end of file diff --git a/include/villas/kernel/kernel.h b/include/villas/kernel/kernel.h index 60df1e080..ee0561c3c 100644 --- a/include/villas/kernel/kernel.h +++ b/include/villas/kernel/kernel.h @@ -2,14 +2,17 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ -#ifndef _LINUX_H_ -#define _LINUX_H_ +/** @addtogroup fpga Kernel @{ */ + +#pragma once #include +#include "config.h" + //#include /** Check if current process has capability \p cap. @@ -17,16 +20,13 @@ * @retval 0 If capabilty is present. * @retval <0 If capability is not present. */ -//int kernel_check_cap(cap_value_t cap): +//int kernel_check_cap(cap_value_t cap); -/** Checks for realtime (PREEMPT_RT) patched kernel. - * - * See https://rt.wiki.kernel.org - * - * @retval 0 Kernel is patched. - * @reval <>0 Kernel is not patched. - */ -int kernel_is_rt(); +/** 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 * @@ -67,4 +67,4 @@ int kernel_get_cacheline_size(); /** Set SMP affinity of IRQ */ int kernel_irq_setaffinity(unsigned irq, uintmax_t new, uintmax_t *old); -#endif /* _LINUX_H_ */ +/** @} */ \ No newline at end of file diff --git a/include/villas/kernel/nl.h b/include/villas/kernel/nl.h index 3f8127542..83fe7245d 100644 --- a/include/villas/kernel/nl.h +++ b/include/villas/kernel/nl.h @@ -2,11 +2,12 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ -#ifndef _NL_H_ -#define _NL_H_ +/** @addtogroup fpga Kernel @{ */ + +#pragma once #include #include @@ -25,4 +26,4 @@ struct nl_sock * nl_init(); /** Close and free global netlink socket. */ void nl_shutdown(); -#endif /* _NL_H_ */ \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/kernel/pci.h b/include/villas/kernel/pci.h index e750e02c6..9f5686972 100644 --- a/include/villas/kernel/pci.h +++ b/include/villas/kernel/pci.h @@ -2,18 +2,19 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel **********************************************************************************/ -#ifndef _PCI_H_ -#define _PCI_H_ +/** @addtogroup fpga Kernel @{ */ + +#pragma once #include "list.h" #define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) #define PCI_FUNC(devfn) ((devfn) & 0x07) -struct pci_dev { +struct pci_device { struct { int vendor; int device; @@ -29,7 +30,7 @@ struct pci_dev { }; struct pci { - struct list devices; /**> List of available PCI devices in the system (struct pci_dev) */ + struct list devices; /**< List of available PCI devices in the system (struct pci_device) */ }; /** Initialize Linux PCI handle. @@ -42,24 +43,20 @@ struct pci { int pci_init(struct pci *p); /** Destroy handle. */ -void pci_destroy(struct pci *p); +int pci_destroy(struct pci *p); -int pci_dev_init(struct pci_dev *d); +int pci_device_parse_slot(struct pci_device *f, const char *str, const char **error); -void pci_dev_destroy(struct pci_dev *d); +int pci_device_parse_id(struct pci_device *f, const char *str, const char **error); -int pci_dev_parse_slot(struct pci_dev *f, const char *str, const char **error); +int pci_device_compare(const struct pci_device *d, const struct pci_device *f); -int pci_dev_parse_id(struct pci_dev *f, const char *str, const char **error); - -int pci_dev_compare(const struct pci_dev *d, const struct pci_dev *f); - -struct pci_dev * pci_lookup_device(struct pci *p, struct pci_dev *filter); +struct pci_device * pci_lookup_device(struct pci *p, struct pci_device *filter); /** Bind a new LKM to the PCI device */ -int pci_attach_driver(struct pci_dev *d, const char *driver); +int pci_attach_driver(struct pci_device *d, const char *driver); /** Return the IOMMU group of this PCI device or -1 if the device is not in a group. */ -int pci_get_iommu_group(struct pci_dev *d); +int pci_get_iommu_group(struct pci_device *d); -#endif /* _PCI_H_ */ \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/kernel/rt.h b/include/villas/kernel/rt.h index 480583fb2..30a7b131f 100644 --- a/include/villas/kernel/rt.h +++ b/include/villas/kernel/rt.h @@ -2,12 +2,26 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ -#ifndef _RT_H_ -#define _RT_H_ +/** @addtogroup fpga Kernel @{ */ -int rt_init(int affinity, int priority); +#pragma once -#endif /* _RT_H_ */ \ No newline at end of file +int rt_init(int priority, int affinity); + +int rt_set_affinity(int affinity); + +int rt_set_priority(int priority); + +/** Checks for realtime (PREEMPT_RT) patched kernel. + * + * See https://rt.wiki.kernel.org + * + * @retval 0 Kernel is patched. + * @reval <>0 Kernel is not patched. + */ +int rt_is_preemptible(); + +/** @} */ \ No newline at end of file diff --git a/include/villas/kernel/tc.h b/include/villas/kernel/tc.h index 1a24f619c..d7f017c5b 100644 --- a/include/villas/kernel/tc.h +++ b/include/villas/kernel/tc.h @@ -7,11 +7,12 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ -#ifndef _TC_H_ -#define _TC_H_ +/** @addtogroup fpga Kernel @{ */ + +#pragma once #include @@ -82,4 +83,4 @@ int tc_netem(struct interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hd */ int tc_mark(struct interface *i, struct rtnl_cls **cls, tc_hdl_t flowid, uint32_t mark); -#endif /* _TC_H_ */ +/** @} */ \ No newline at end of file diff --git a/include/villas/kernel/vfio.h b/include/villas/kernel/vfio.h index 401523b9d..3fce78657 100644 --- a/include/villas/kernel/vfio.h +++ b/include/villas/kernel/vfio.h @@ -2,12 +2,14 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel *********************************************************************************/ -#ifndef _VFIO_H_ -#define _VFIO_H_ +/** @addtogroup fpga Kernel @{ */ +#pragma once + +#include #include #include @@ -18,22 +20,21 @@ #define VFIO_DEV(x) "/dev/vfio/" x -/* Forward declaration */ -struct dma_mem; -struct pci_dev; +/* Forward declarations */ +struct pci_device; struct vfio_group { - int fd; /**< VFIO group file descriptor */ - int index; /**< Index of the IOMMU group as listed under /sys/kernel/iommu_groups/ */ + int fd; /**< VFIO group file descriptor */ + int index; /**< Index of the IOMMU group as listed under /sys/kernel/iommu_groups/ */ - struct vfio_group_status status; /**< Status of group */ + struct vfio_group_status status; /**< Status of group */ struct list devices; - struct vfio_container *container; /**< The VFIO container to which this group is belonging */ + struct vfio_container *container; /**< The VFIO container to which this group is belonging */ }; -struct vfio_dev { +struct vfio_device { char *name; /**< Name of the device as listed under /sys/kernel/iommu_groups/[vfio_group::index]/devices/ */ int fd; /**< VFIO device file descriptor */ @@ -43,7 +44,7 @@ struct vfio_dev { void **mappings; - struct pci_dev *pdev; /**< libpci handle of the device */ + struct pci_device *pci_device; /**< libpci handle of the device */ struct vfio_group *group; /**< The VFIO group this device belongs to */ }; @@ -52,7 +53,7 @@ struct vfio_container { int version; int extensions; - void *iova_next; /**< Next free IOVA address */ + uint64_t iova_next; /**< Next free IOVA address */ struct list groups; }; @@ -64,48 +65,48 @@ int vfio_init(struct vfio_container *c); int vfio_group_attach(struct vfio_group *g, struct vfio_container *c, int index); /** Initialize a VFIO device, lookup the VFIO group it belongs to, create the group if not already existing. */ -int vfio_dev_attach(struct vfio_dev *d, struct vfio_container *c, const char *name, int index); +int vfio_device_attach(struct vfio_device *d, struct vfio_container *c, const char *name, int index); -/** Initialie a VFIO-PCI device (uses vfio_dev_attach() internally) */ -int vfio_pci_attach(struct vfio_dev *d, struct vfio_container *c, struct pci_dev *pdev); +/** Initialie a VFIO-PCI device (uses vfio_device_attach() internally) */ +int vfio_pci_attach(struct vfio_device *d, struct vfio_container *c, struct pci_device *pdev); /** Hot resets a VFIO-PCI device */ -int vfio_pci_reset(struct vfio_dev *d); +int vfio_pci_reset(struct vfio_device *d); -int vfio_pci_msi_init(struct vfio_dev *d, int efds[32]); +int vfio_pci_msi_init(struct vfio_device *d, int efds[32]); -int vfio_pci_msi_deinit(struct vfio_dev *d, int efds[32]); +int vfio_pci_msi_deinit(struct vfio_device *d, int efds[32]); -int vfio_pci_msi_find(struct vfio_dev *d, int nos[32]); +int vfio_pci_msi_find(struct vfio_device *d, int nos[32]); /** Enable memory accesses and bus mastering for PCI device */ -int vfio_pci_enable(struct vfio_dev *d); +int vfio_pci_enable(struct vfio_device *d); /** Reset a VFIO device */ -int vfio_dev_reset(struct vfio_dev *d); +int vfio_device_reset(struct vfio_device *d); /** Release memory and close container */ int vfio_destroy(struct vfio_container *c); /** Release memory of group */ -void vfio_group_destroy(struct vfio_group *g); +int vfio_group_destroy(struct vfio_group *g); /** Release memory of device */ -void vfio_dev_destroy(struct vfio_dev *g); +int vfio_device_destroy(struct vfio_device *g); /** Print a dump of all attached groups and their devices including regions and IRQs */ void vfio_dump(struct vfio_container *c); /** Map a device memory region to the application address space (e.g. PCI BARs) */ -void * vfio_map_region(struct vfio_dev *d, int idx); +void * vfio_map_region(struct vfio_device *d, int idx); /** Map VM to an IOVA, which is accessible by devices in the container */ -int vfio_map_dma(struct vfio_container *c, struct dma_mem *mem); +int vfio_map_dma(struct vfio_container *c, uint64_t virt, uint64_t phys, size_t len); /** Unmap DMA memory */ -int vfio_unmap_dma(struct vfio_container *c, struct dma_mem *mem); +int vfio_unmap_dma(struct vfio_container *c, uint64_t virt, uint64_t phys, size_t len); /** munmap() a region which has been mapped by vfio_map_region() */ -int vfio_unmap_region(struct vfio_dev *d, int idx); +int vfio_unmap_region(struct vfio_device *d, int idx); -#endif /* _VFIO_H_ */ +/** @} */ \ No newline at end of file diff --git a/include/villas/list.h b/include/villas/list.h index 661bd0459..00ff9ee15 100644 --- a/include/villas/list.h +++ b/include/villas/list.h @@ -8,15 +8,16 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 20177, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ -#ifndef _LIST_H_ -#define _LIST_H_ +#pragma once #include #include +#include "common.h" + #define LIST_CHUNKSIZE 16 /** Static list initialization */ @@ -24,22 +25,22 @@ .array = NULL, \ .length = 0, \ .capacity = 0, \ - .lock = PTHREAD_MUTEX_INITIALIZER \ + .lock = PTHREAD_MUTEX_INITIALIZER, \ + .state = STATE_INITIALIZED \ } #define list_length(list) ((list)->length) -#define list_at(list, index) ((list)->length > index ? (list)->array[index] : NULL) +#define list_at_safe(list, index) ((list)->length > index ? (list)->array[index] : NULL) +#define list_at(list, index) ((list)->array[index]) #define list_first(list) list_at(list, 0) #define list_last(list) list_at(list, (list)->length-1) -#define list_foreach(ptr, list) for (int _i = 0, _p; _p = 1, _i < (list)->length; _i++) \ - for (ptr = (list)->array[_i]; _p--; ) /** Callback to destroy list elements. * * @param data A pointer to the data which should be freed. */ -typedef void (*dtor_cb_t)(void *); +typedef int (*dtor_cb_t)(void *); /** Callback to search or sort a list. */ typedef int (*cmp_cb_t)(const void *, const void *); @@ -50,6 +51,7 @@ struct list { size_t capacity; /**< Size of list::array in elements */ size_t length; /**< Number of elements of list::array which are in use */ pthread_mutex_t lock; /**< A mutex to allow thread-safe accesses */ + enum state state; /**< The state of this list. */ }; /** Initialize a list. @@ -64,7 +66,7 @@ void list_init(struct list *l); * @param dtor A function pointer to a desctructor which will be called for every list item when the list is destroyed. * @param l A pointer to the list data structure. */ -void list_destroy(struct list *l, dtor_cb_t dtor, bool free); +int list_destroy(struct list *l, dtor_cb_t dtor, bool free); /** Append an element to the end of the list */ void list_push(struct list *l, void *p); @@ -95,6 +97,4 @@ int list_count(struct list *l, cmp_cb_t cmp, void *ctx); int list_contains(struct list *l, void *p); /** Sort the list using the quicksort algorithm of libc */ -void list_sort(struct list *l, cmp_cb_t cmp); - -#endif /* _LIST_H_ */ +void list_sort(struct list *l, cmp_cb_t cmp); \ No newline at end of file diff --git a/include/villas/log.h b/include/villas/log.h index 1c0ed9a69..5b4a968d3 100644 --- a/include/villas/log.h +++ b/include/villas/log.h @@ -2,16 +2,16 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ -#ifndef _LOG_H_ -#define _LOG_H_ +#pragma once #include +#include #include -#include "utils.h" +#include "common.h" #ifdef __GNUC__ #define INDENT int __attribute__ ((__cleanup__(log_outdent), unused)) _old_indent = log_indent(1); @@ -30,24 +30,67 @@ * * To be or-ed with the debug level */ -enum debug_facilities { - DBG_POOL = (1 << 8), - DBG_QUEUE = (1 << 9), - DBG_CONFIG = (1 << 10), - DBG_HOOK = (1 << 11), - DBG_PATH = (1 << 12), - DBG_MEM = (1 << 13), +enum log_facilities { + LOG_POOL = (1L << 8), + LOG_QUEUE = (1L << 9), + LOG_CONFIG = (1L << 10), + LOG_HOOK = (1L << 11), + LOG_PATH = (1L << 12), + LOG_NODE = (1L << 13), + LOG_MEM = (1L << 14), + LOG_WEB = (1L << 15), + LOG_API = (1L << 16), + LOG_LOG = (1L << 17), + LOG_VFIO = (1L << 18), + LOG_PCI = (1L << 19), + LOG_XIL = (1L << 20), + LOG_TC = (1L << 21), + LOG_IF = (1L << 22), /* Node-types */ - DBG_SOCKET = (1 << 16), - DBG_FILE = (1 << 17), - DBG_FPGA = (1 << 18), - DBG_NGSI = (1 << 19), - DBG_WEBSOCKET = (1 << 20), - DBG_OPAL = (1 << 21), - DBG_NODE = (0xFF << 16) + LOG_SOCKET = (1L << 23), + LOG_FILE = (1L << 24), + LOG_FPGA = (1L << 25), + LOG_NGSI = (1L << 26), + LOG_WEBSOCKET = (1L << 27), + LOG_OPAL = (1L << 28), + + /* Classes */ + LOG_NODES = LOG_NODE | LOG_SOCKET | LOG_FILE | LOG_FPGA | LOG_NGSI | LOG_WEBSOCKET | LOG_OPAL, + LOG_KERNEL = LOG_VFIO | LOG_PCI | LOG_TC | LOG_IF, + LOG_ALL = ~0xFF }; +struct log { + enum state state; + + struct timespec epoch; /**< A global clock used to prefix the log messages. */ + + /** Debug level used by the debug() macro. + * It defaults to V (defined by the Makefile) and can be + * overwritten by the 'debug' setting in the configuration file. */ + int level; + + /** Debug facilities used by the debug() macro. */ + long facilities; + + /** Path of the log file */ + const char *path; + + /** Send all log output to this file / stdout / stderr */ + FILE *file; +}; + +/** Initialize log object */ +int log_init(struct log *l, int level, long faciltities); + +int log_start(struct log *l); + +int log_stop(struct log *l); + +/** Destroy log object */ +int log_destroy(struct log *l); + /** Change log indention for current thread. * * The argument level can be negative! @@ -61,23 +104,30 @@ int log_indent(int levels); */ void log_outdent(int *); -/** Set the verbosity level of debug messages. +/** Set logging facilities based on expression. * - * @param lvl The new debug level. - * @param fac The new mask for debug facilities. + * Currently we support two types of expressions: + * 1. A comma seperated list of logging facilities + * 2. A comma seperated list of logging facilities which is prefixes with an exclamation mark '!' + * + * The first case enables only faciltities which are in the list. + * The second case enables all faciltities with exception of those which are in the list. + * + * @param expression The expression + * @return The new facilties mask (see enum log_faciltities) */ -void log_setlevel(int lvl, int fac); +int log_set_facility_expression(struct log *l, const char *expression); -/** Reset the wallclock of debug messages. */ -void log_init(); +/** Parse logging configuration. */ +int log_parse(struct log *l, config_setting_t *cfg); /** Logs variadic messages to stdout. * * @param lvl The log level * @param fmt The format string (printf alike) */ -void log_print(const char *lvl, const char *fmt, ...) - __attribute__ ((format(printf, 2, 3))); +void log_print(struct log *l, const char *lvl, const char *fmt, ...) + __attribute__ ((format(printf, 3, 4))); /** Logs variadic messages to stdout. * @@ -85,10 +135,10 @@ void log_print(const char *lvl, const char *fmt, ...) * @param fmt The format string (printf alike) * @param va The variadic argument list (see stdarg.h) */ -void log_vprint(const char *lvl, const char *fmt, va_list va); +void log_vprint(struct log *l, const char *lvl, const char *fmt, va_list va); /** Printf alike debug message with level. */ -void debug(int lvl, const char *fmt, ...) +void debug(long lvl, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); /** Print a horizontal line. */ @@ -116,7 +166,4 @@ void serror(const char *fmt, ...) /** Print configuration error and exit. */ void cerror(config_setting_t *cfg, const char *fmt, ...) - __attribute__ ((format(printf, 2, 3))); - -#endif /* _LOG_H_ */ - + __attribute__ ((format(printf, 2, 3))); \ No newline at end of file diff --git a/include/villas/mapping.h b/include/villas/mapping.h new file mode 100644 index 000000000..c468cb4bd --- /dev/null +++ b/include/villas/mapping.h @@ -0,0 +1,83 @@ +/** Sample value remapping for mux. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#pragma once + +#include + +#include "stats.h" +#include "common.h" +#include "list.h" + +/* Forward declarations */ +struct stats; +struct node; +struct sample; +struct list; + +struct mapping_entry { + struct node *source; /**< Unused for now. */ + int length; + + enum { + MAPPING_TYPE_DATA, + MAPPING_TYPE_STATS, + MAPPING_TYPE_HEADER, + MAPPING_TYPE_TIMESTAMP + } type; + + union { + struct { + int offset; + } data; + struct { + enum stats_id id; + enum stats_type { + MAPPING_STATS_TYPE_LAST, + MAPPING_STATS_TYPE_HIGHEST, + MAPPING_STATS_TYPE_LOWEST, + MAPPING_STATS_TYPE_MEAN, + MAPPING_STATS_TYPE_VAR, + MAPPING_STATS_TYPE_STDDEV, + MAPPING_STATS_TYPE_TOTAL + } type; + } stats; + struct { + enum header_type { + MAPPING_HEADER_LENGTH, + MAPPING_HEADER_SEQUENCE, + } id; + } header; + struct { + enum timestamp_type { + MAPPING_TIMESTAMP_ORIGIN, + MAPPING_TIMESTAMP_RECEIVED + } id; + } timestamp; + }; +}; + +struct mapping { + enum state state; + + int real_length; + + struct list entries; +}; + +int mapping_init(struct mapping *m); + +int mapping_parse(struct mapping *m, config_setting_t *cfg); + +int mapping_check(struct mapping *m); + +int mapping_destroy(struct mapping *m); + +int mapping_remap(struct mapping *m, struct sample *orig, struct sample *remapped, struct stats *s); + +int mapping_entry_parse(struct mapping_entry *e, config_setting_t *cfg); + +int mapping_entry_parse_str(struct mapping_entry *e, const char *str); \ No newline at end of file diff --git a/include/villas/memory.h b/include/villas/memory.h index 979ffe4c9..0715df4a6 100644 --- a/include/villas/memory.h +++ b/include/villas/memory.h @@ -2,18 +2,17 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC - */ + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ #include #include -#ifndef _MEMORY_H_ -#define _MEMORY_H_ +#pragma once #define HUGEPAGESIZE (1 << 21) -typedef void *(*memzone_allocator_t)(size_t len); +typedef void *(*memzone_allocator_t)(size_t len, size_t alignment); typedef int (*memzone_deallocator_t)(void *ptr, size_t len); enum memtype_flags { @@ -42,6 +41,9 @@ struct memzone { size_t len; }; +/** Initilialize memory subsystem */ +int memory_init(int hugepages); + /** Allocate \p len bytes memory of type \p m. * * @retval NULL If allocation failed. @@ -54,6 +56,4 @@ void * memory_alloc_aligned(const struct memtype *m, size_t len, size_t alignmen int memory_free(const struct memtype *m, void *ptr, size_t len); extern const struct memtype memtype_heap; -extern const struct memtype memtype_hugepage; - -#endif /* _MEMORY_H_ */ \ No newline at end of file +extern const struct memtype memtype_hugepage; \ No newline at end of file diff --git a/include/villas/msg.h b/include/villas/msg.h index f2d6afeb4..130e06be1 100644 --- a/include/villas/msg.h +++ b/include/villas/msg.h @@ -2,11 +2,10 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ -#ifndef _MSG_H_ -#define _MSG_H_ +#pragma once #include @@ -35,6 +34,4 @@ void msg_hdr_swap(struct msg *m); * @retval 0 The message header is valid. * @retval <0 The message header is invalid. */ -int msg_verify(struct msg *m); - -#endif /* _MSG_H_ */ +int msg_verify(struct msg *m); \ No newline at end of file diff --git a/include/villas/msg_format.h b/include/villas/msg_format.h index 2af19f44d..e63f90db0 100644 --- a/include/villas/msg_format.h +++ b/include/villas/msg_format.h @@ -2,11 +2,10 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ -#ifndef _MSG_FORMAT_H_ -#define _MSG_FORMAT_H_ +#pragma once #include @@ -93,6 +92,4 @@ struct msg float f; /**< Floating point values (note msg::endian) */ uint32_t i; /**< Integer values (note msg::endian) */ } data[]; -} __attribute__((packed)); - -#endif /* _MSG_FORMAT_H_ */ +} __attribute__((packed)); \ No newline at end of file diff --git a/include/villas/node.h b/include/villas/node.h index 3ae39fff1..e2bdafe33 100644 --- a/include/villas/node.h +++ b/include/villas/node.h @@ -2,34 +2,23 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC * * @addtogroup node Node * @{ *********************************************************************************/ -#ifndef _NODE_H_ -#define _NODE_H_ +#pragma once #include #include #include +#include "node_type.h" #include "sample.h" #include "list.h" #include "queue.h" - -/* Helper macros for virtual node type */ -#define REGISTER_NODE_TYPE(vt) \ -__attribute__((constructor)) static void __register() { \ - list_push(&node_types, vt); \ -} - -extern struct list node_types; /**< Vtable for virtual node sub types */ - -/* Forward declarations */ -struct config_setting_t cfg; -struct node_type; +#include "common.h" /** The data structure for a node. * @@ -47,163 +36,28 @@ struct node int affinity; /**< CPU Affinity of this node */ unsigned long sequence; /**< This is a counter of received samples, in case the node-type does not generate sequence numbers itself. */ - - enum node_state { - NODE_INVALID, /**< This node object is not in a valid state. */ - NODE_CREATED, /**< This node has been parsed from the configuration. */ - NODE_STARTING, /**< This node is currently being started. */ - NODE_RUNNING, /**< This node has been started by calling node_open() */ - NODE_STOPPING, /**< This node is currently shutting down. */ - NODE_STOPPED /**< Node was running, but has been stopped by calling node_close() */ - } state; /**< Node state */ - + + enum state state; + struct node_type *_vt; /**< Virtual functions (C++ OOP style) */ void *_vd; /**< Virtual data (used by struct node::_vt functions) */ config_setting_t *cfg; /**< A pointer to the libconfig object which instantiated this node */ }; -/** C++ like vtable construct for node_types */ -struct node_type { - const char *name; /**< The unique name of this node. This must be allways the first member! */ - const char *description; /**< A short description of this node type. Will be shown in help text. */ - int vectorize; /**< Maximal vector length supported by this node type. Zero is unlimited. */ +int node_init(struct node *n, struct node_type *vt); - struct list instances; /**< A list of all existing nodes of this type. */ - size_t size; /**< Size of private data bock. @see node::_vd */ - - enum node_type_state { - NODE_TYPE_UNINITIALIZED = 0, - NODE_TYPE_INITIALIZED - } state; - - /** Global initialization per node type. - * - * This callback is invoked once per node-type. - * - * @param argc Number of arguments passed to the server executable (see main()). - * @param argv Array of arguments passed to the server executable (see main()). - * @param cfg Root libconfig object of global configuration file. - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ - int (*init)(int argc, char * argv[], config_setting_t *cfg); - - /** Global de-initialization per node type. - * - * This callback is invoked once per node-type. - * - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ - int (*deinit)(); - - /** Allocate memory for an instance of this type. - * - * @return A pointer to the node-type specific private data. - */ - void * (*create)(); - - /** Free memory of an instance of this type. - * - * @param n A pointer to the node object. - */ - int (*destroy)(struct node *n); - - /** Parse node connection details.‚ - * - * @param n A pointer to the node object. - * @param cfg A libconfig object pointing to the node. - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ - int (*parse)(struct node *n, config_setting_t *cfg); - - /** Returns a string with a textual represenation of this node. - * - * @param n A pointer to the node object. - * @return A pointer to a dynamically allocated string. Must be freed(). - */ - char * (*print)(struct node *n); - - /** Opens the connection to this node. - * - * @param n A pointer to the node object. - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ - int (*open) (struct node *n); - - /** Close the connection to this node. - * - * @param n A pointer to the node object. - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ - int (*close)(struct node *n); - - /** Receive multiple messages at once. - * - * Messages are received with a single recvmsg() syscall by - * using gathering techniques (struct iovec). - * The messages will be stored in a circular buffer / array @p m. - * Indexes used to address @p m will wrap around after len messages. - * Some node types might only support to receive one message at a time. - * - * @param n A pointer to the node object. - * @param smps An array of pointers to memory blocks where the function should store received samples. - * @param cnt The number of messages which should be received. - * @return The number of messages actually received. - */ - int (*read) (struct node *n, struct sample *smps[], unsigned cnt); - - /** Send multiple messages in a single datagram / packet. - * - * Messages are sent with a single sendmsg() syscall by - * using gathering techniques (struct iovec). - * The messages have to be stored in a circular buffer / array m. - * So the indexes will wrap around after len. - * - * @param n A pointer to the node object. - * @param smps An array of pointers to memory blocks where samples read from. - * @param cnt The number of messages which should be sent. - * @return The number of messages actually sent. - */ - int (*write)(struct node *n, struct sample *smps[], unsigned cnt); - - /** Reverse source and destination of a node. - * - * This is not supported by all node types! - * - * @param n A pointer to the node object. - */ - int (*reverse)(struct node *n); -}; - -/** Initialize all registered node type subsystems. +/** Parse a single node and add it to the global configuration. * - * @see node_type::init + * @param cfg A libconfig object pointing to the node. + * @param nodes Add new nodes to this linked list. + * @retval 0 Success. Everything went well. + * @retval <0 Error. Something went wrong. */ -int node_init(struct node_type *vt, int argc, char *argv[], config_setting_t *cfg); +int node_parse(struct node *n, config_setting_t *cfg); -/** De-initialize node type subsystems. - * - * @see node_type::deinit - */ -int node_deinit(struct node_type *vt); - -/** Create a node by allocating dynamic memory. - * - * @see node_type::create - * @param vt A pointer to the node-type table of virtual functions. - */ -struct node * node_create(struct node_type *vt); - -/** Destroy node by freeing dynamically allocated memory. - * - * @see node_type::destroy - */ -void node_destroy(struct node *n); +/** Validate node configuration. */ +int node_check(struct node *n); /** Start operation of a node. * @@ -217,11 +71,11 @@ int node_start(struct node *n); */ int node_stop(struct node *n); -/** Parse node connection details. +/** Destroy node by freeing dynamically allocated memory. * - * @see node_type::parse + * @see node_type::destroy */ -int node_parse(struct node *n, config_setting_t *cfg); +int node_destroy(struct node *n); /** Return a pointer to a string which should be used to print this node. * @@ -241,9 +95,6 @@ char * node_name(struct node *n); */ char * node_name_long(struct node *n); -/** Return a pointer to a string which describes the node type */ -const char * node_name_type(struct node *n); - /** Reverse local and remote socket address. * * @see node_type::reverse @@ -254,4 +105,16 @@ int node_read(struct node *n, struct sample *smps[], unsigned cnt); int node_write(struct node *n, struct sample *smps[], unsigned cnt); -#endif /** _NODE_H_ @} */ +/** Parse an array or single node and checks if they exist in the "nodes" section. + * + * Examples: + * out = [ "sintef", "scedu" ] + * out = "acs" + * + * @param cfg The libconfig object handle for "out". + * @param nodes The nodes will be added to this list. + * @param all This list contains all valid nodes. + */ +int node_parse_list(struct list *list, config_setting_t *cfg, struct list *all); + +/** @} */ \ No newline at end of file diff --git a/include/villas/node_type.h b/include/villas/node_type.h new file mode 100644 index 000000000..cc4e35674 --- /dev/null +++ b/include/villas/node_type.h @@ -0,0 +1,146 @@ +/** Nodes + * + * @file + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + * + * @addtogroup node Node + * @{ + *********************************************************************************/ + +#pragma once + +#include + +#include "list.h" +#include "common.h" + +/* Forward declarations */ +struct node; +struct sample; + +/** C++ like vtable construct for node_types */ +struct node_type { + int vectorize; /**< Maximal vector length supported by this node type. Zero is unlimited. */ + + struct list instances; /**< A list of all existing nodes of this type. */ + size_t size; /**< Size of private data bock. @see node::_vd */ + + enum state state; + + /** Global initialization per node type. + * + * This callback is invoked once per node-type. + * + * @param argc Number of arguments passed to the server executable (see main()). + * @param argv Array of arguments passed to the server executable (see main()). + * @param cfg Root libconfig object of global configuration file. + * @retval 0 Success. Everything went well. + * @retval <0 Error. Something went wrong. + */ + int (*init)(int argc, char *argv[], config_setting_t *cfg); + + /** Global de-initialization per node type. + * + * This callback is invoked once per node-type. + * + * @retval 0 Success. Everything went well. + * @retval <0 Error. Something went wrong. + */ + int (*deinit)(); + + /** Allocate memory for an instance of this type. + * + * @return A pointer to the node-type specific private data. + */ + void * (*create)(); + + /** Free memory of an instance of this type. + * + * @param n A pointer to the node object. + */ + int (*destroy)(struct node *n); + + /** Parse node connection details.‚ + * + * @param n A pointer to the node object. + * @param cfg A libconfig object pointing to the node. + * @retval 0 Success. Everything went well. + * @retval <0 Error. Something went wrong. + */ + int (*parse)(struct node *n, config_setting_t *cfg); + + /** Returns a string with a textual represenation of this node. + * + * @param n A pointer to the node object. + * @return A pointer to a dynamically allocated string. Must be freed(). + */ + char * (*print)(struct node *n); + + /** Start this node. + * + * @param n A pointer to the node object. + * @retval 0 Success. Everything went well. + * @retval <0 Error. Something went wrong. + */ + int (*start) (struct node *n); + + /** Stop this node. + * + * @param n A pointer to the node object. + * @retval 0 Success. Everything went well. + * @retval <0 Error. Something went wrong. + */ + int (*stop)(struct node *n); + + /** Receive multiple messages at once. + * + * Messages are received with a single recvmsg() syscall by + * using gathering techniques (struct iovec). + * The messages will be stored in a circular buffer / array @p m. + * Indexes used to address @p m will wrap around after len messages. + * Some node types might only support to receive one message at a time. + * + * @param n A pointer to the node object. + * @param smps An array of pointers to memory blocks where the function should store received samples. + * @param cnt The number of messages which should be received. + * @return The number of messages actually received. + */ + int (*read) (struct node *n, struct sample *smps[], unsigned cnt); + + /** Send multiple messages in a single datagram / packet. + * + * Messages are sent with a single sendmsg() syscall by + * using gathering techniques (struct iovec). + * The messages have to be stored in a circular buffer / array m. + * So the indexes will wrap around after len. + * + * @param n A pointer to the node object. + * @param smps An array of pointers to memory blocks where samples read from. + * @param cnt The number of messages which should be sent. + * @return The number of messages actually sent. + */ + int (*write)(struct node *n, struct sample *smps[], unsigned cnt); + + /** Reverse source and destination of a node. + * + * This is not supported by all node types! + * + * @param n A pointer to the node object. + */ + int (*reverse)(struct node *n); +}; + +/** Initialize all registered node type subsystems. + * + * @see node_type::init + */ +int node_type_start(struct node_type *vt, int argc, char *argv[], config_setting_t *cfg); + +/** De-initialize node type subsystems. + * + * @see node_type::deinit + */ +int node_type_stop(struct node_type *vt); + +/** @} */ \ No newline at end of file diff --git a/include/villas/nodes/cbuilder.h b/include/villas/nodes/cbuilder.h index 2f42b2ed5..cb83ced7f 100644 --- a/include/villas/nodes/cbuilder.h +++ b/include/villas/nodes/cbuilder.h @@ -2,29 +2,38 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Steffen Vogel - **********************************************************************************/ - -#ifndef _CBUILDER_H_ -#define _CBUILDER_H_ + * @copyright 2017, Steffen Vogel + *********************************************************************************/ + +/** + * @addtogroup cbuilder RTDS CBuilder model node + * @ingroup node + * @{ + */ + +#pragma once #include #include "list.h" -/* Helper macros for registering new models */ -#define REGISTER_CBMODEL(cb) \ -__attribute__((constructor)) static void __register() { \ - list_push(&cbmodels, cb); \ -} +/* Forward declaration */ +struct cbuilder; -extern struct list cbmodels; /**< Table of existing CBuilder models */ +struct cbuilder_model { + void (*code)(); + void (*ram)(); + + int (*init)(struct cbuilder *cb); + int (*read)(float inputs[], int len); + int (*write)(float outputs[], int len); +}; struct cbuilder { unsigned long step, read; double timestep; - struct cbmodel *model; + struct cbuilder_model *model; float *params; int paramlen; @@ -39,15 +48,4 @@ struct cbuilder { pthread_cond_t cv; }; -struct cbmodel { - char *name; - - void (*code)(); - void (*ram)(); - - int (*init)(struct cbuilder *cb); - int (*read)(float inputs[], int len); - int (*write)(float outputs[], int len); -}; - -#endif /* _CBUILDER_H_ */ \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/nodes/file.h b/include/villas/nodes/file.h index a582be003..d8355421b 100644 --- a/include/villas/nodes/file.h +++ b/include/villas/nodes/file.h @@ -4,18 +4,18 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC - */ + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + /** * @addtogroup file File-IO node type * @ingroup node * @{ - *********************************************************************************/ + */ +#pragma once -#ifndef _FILE_H_ -#define _FILE_H_ - +#include "advio.h" #include "node.h" #define FILE_MAX_PATHLEN 512 @@ -27,12 +27,12 @@ enum { struct file { struct file_direction { - FILE *handle; /**< libc: stdio file handle */ + AFILE *handle; /**< libc: stdio file handle */ const char *mode; /**< libc: fopen() mode */ const char *fmt; /**< Format string for file name. */ - char *path; /**< Real file name */ + char *uri; /**< Real file name */ int chunk; /**< Current chunk number. */ int split; /**< Split file every file::split mega bytes. */ @@ -45,7 +45,7 @@ struct file { EPOCH_ABSOLUTE } read_epoch_mode; /**< Specifies how file::offset is calculated. */ - struct timespec read_first; /**< The first timestamp in the file file::path_in */ + struct timespec read_first; /**< The first timestamp in the file file::{read,write}::uri */ struct timespec read_epoch; /**< The epoch timestamp from the configuration. */ struct timespec read_offset; /**< An offset between the timestamp in the input file and the current time */ @@ -60,10 +60,10 @@ char * file_print(struct node *n); int file_parse(struct node *n, config_setting_t *cfg); /** @see node_vtable::open */ -int file_open(struct node *n); +int file_start(struct node *n); /** @see node_vtable::close */ -int file_close(struct node *n); +int file_stop(struct node *n); /** @see node_vtable::read */ int file_read(struct node *n, struct sample *smps[], unsigned cnt); @@ -71,4 +71,4 @@ int file_read(struct node *n, struct sample *smps[], unsigned cnt); /** @see node_vtable::write */ int file_write(struct node *n, struct sample *smps[], unsigned cnt); -#endif /** _FILE_H_ @} */ +/** @} */ diff --git a/include/villas/nodes/fpga.h b/include/villas/nodes/fpga.h index 2e4f8a302..e201434b7 100644 --- a/include/villas/nodes/fpga.h +++ b/include/villas/nodes/fpga.h @@ -4,52 +4,31 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Steffen Vogel - */ -/** - * @addtogroup fpga VILLASnode - * @ingroup node - * @{ + * @copyright 2017, Steffen Vogel *********************************************************************************/ -#ifndef _FPGA_H_ -#define _FPGA_H_ +/** + * @addtogroup fpga VILLASfpga + * @ingroup node + * @{ + */ + +#pragma once #include "kernel/vfio.h" #include "kernel/pci.h" -#include "fpga/dma.h" -#include "fpga/ip.h" -#include "fpga/intc.h" +#include "fpga/ips/dma.h" #include "node.h" #include "list.h" +/* Forward declarations */ +struct fpga_ip; + +/** The node type */ struct fpga { - 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 ip *intc; - struct ip *reset; - struct ip *sw; - - config_setting_t *cfg; -}; - -struct fpga_dm { - struct ip *ip; - const char *ip_name; + struct fpga_ip *ip; int use_irqs; @@ -59,12 +38,10 @@ struct fpga_dm { FPGA_DM_DMA, FPGA_DM_FIFO } type; - - struct fpga *card; }; /** @see node_vtable::init */ -int fpga_init(int argc, char * argv[], config_setting_t *cfg); +int fpga_init(int argc, char *argv[], config_setting_t *cfg); /** @see node_vtable::deinit */ int fpga_deinit(); @@ -73,16 +50,18 @@ int fpga_deinit(); int fpga_parse(struct node *n, config_setting_t *cfg); /** Parse the 'fpga' section in the configuration file */ -int fpga_parse_card(struct fpga *v, int argc, char * argv[], config_setting_t *cfg); +int fpga_parse_cards(config_setting_t *cfg); + +struct fpga_card * fpga_lookup_card(const char *name); /** @see node_vtable::print */ char * fpga_print(struct node *n); /** @see node_vtable::open */ -int fpga_open(struct node *n); +int fpga_start(struct node *n); /** @see node_vtable::close */ -int fpga_close(struct node *n); +int fpga_stop(struct node *n); /** @see node_vtable::read */ int fpga_read(struct node *n, struct sample *smps[], unsigned cnt); @@ -99,4 +78,4 @@ int fpga_reset(struct fpga *f); /** Dump some details about the fpga card */ void fpga_dump(struct fpga *f); -#endif /** _FPGA_H_ @} */ +/** @} */ diff --git a/include/villas/nodes/ngsi.h b/include/villas/nodes/ngsi.h index faea7792b..45c6be49d 100644 --- a/include/villas/nodes/ngsi.h +++ b/include/villas/nodes/ngsi.h @@ -8,16 +8,16 @@ * @see http://technical.openmobilealliance.org/Technical/Release_Program/docs/NGSI/V1_0-20120529-A/OMA-TS-NGSI_Context_Management-V1_0-20120529-A.pdf * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC - */ + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + /** * @addtogroup ngsi FIRWARE NGSI 9/10 RESTful HTTP API * @ingroup node * @{ - **********************************************************************************/ + */ -#ifndef _NGSI_H_ -#define _NGSI_H_ +#pragma once #include #include @@ -25,7 +25,7 @@ #include "list.h" #include "config.h" #include "msg.h" -#include "cfg.h" +#include "super_node.h" #include "node.h" struct node; @@ -68,10 +68,10 @@ int ngsi_parse(struct node *n, config_setting_t *cfg); char * ngsi_print(struct node *n); /** @see node_vtable::open */ -int ngsi_open(struct node *n); +int ngsi_start(struct node *n); /** @see node_vtable::close */ -int ngsi_close(struct node *n); +int ngsi_stop(struct node *n); /** @see node_vtable::read */ int ngsi_read(struct node *n, struct sample *smps[], unsigned cnt); @@ -79,4 +79,4 @@ int ngsi_read(struct node *n, struct sample *smps[], unsigned cnt); /** @see node_vtable::write */ int ngsi_write(struct node *n, struct sample *smps[], unsigned cnt); -#endif /** _NGSI_H_ @} */ \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/nodes/opal.h b/include/villas/nodes/opal.h index b65b9586e..4b07fb0d1 100644 --- a/include/villas/nodes/opal.h +++ b/include/villas/nodes/opal.h @@ -4,16 +4,16 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC - */ + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + /** * @ingroup node * @addtogroup opal OPAL-RT Async Process node type * @{ - **********************************************************************************/ + */ -#ifndef _OPAL_H_ -#define _OPAL_H_ +#pragma once #include @@ -60,10 +60,10 @@ char * opal_print(struct node *n); int opal_print_global(); /** @see node_vtable::open */ -int opal_open(struct node *n); +int opal_start(struct node *n); /** @see node_vtable::close */ -int opal_close(struct node *n); +int opal_stop(struct node *n); /** @see node_vtable::read */ int opal_read(struct node *n, struct sample *smps[], unsigned cnt); @@ -71,4 +71,4 @@ int opal_read(struct node *n, struct sample *smps[], unsigned cnt); /** @see node_vtable::write */ int opal_write(struct node *n, struct sample *smps[], unsigned cnt); -#endif /** _OPAL_H_ @} */ +/** @} */ \ No newline at end of file diff --git a/include/villas/nodes/socket.h b/include/villas/nodes/socket.h index 12ab2f9f4..cc1db7628 100644 --- a/include/villas/nodes/socket.h +++ b/include/villas/nodes/socket.h @@ -4,16 +4,16 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC - */ + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + /** * @addtogroup socket BSD Socket Node Type * @ingroup node * @{ - *********************************************************************************/ + */ -#ifndef _SOCKET_H_ -#define _SOCKET_H_ +#pragma once #include #include @@ -64,10 +64,10 @@ int socket_init(int argc, char *argv[], config_setting_t *cfg); int socket_deinit(); /** @see node_vtable::open */ -int socket_open(struct node *n); +int socket_start(struct node *n); /** @see node_vtable::close */ -int socket_close(struct node *n); +int socket_stop(struct node *n); /** @see node_vtable::write */ int socket_write(struct node *n, struct sample *smps[], unsigned cnt); @@ -107,4 +107,4 @@ char * socket_print_addr(struct sockaddr *saddr); */ int socket_parse_addr(const char *str, struct sockaddr *sa, enum socket_layer layer, int flags); -#endif /** _SOCKET_H_ @} */ +/** @} */ \ No newline at end of file diff --git a/include/villas/nodes/websocket.h b/include/villas/nodes/websocket.h index 56416103c..1a51bec63 100644 --- a/include/villas/nodes/websocket.h +++ b/include/villas/nodes/websocket.h @@ -5,17 +5,18 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC - */ + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + /** * @addtogroup websockets WebSockets node type * @ingroup node * @{ - *********************************************************************************/ + */ +#pragma once -#ifndef _WEBSOCKET_H_ -#define _WEBSOCKET_H_ +#include #include "node.h" #include "pool.h" @@ -26,52 +27,51 @@ struct lws; /** Internal data per websocket node */ struct websocket { - struct list connections; /**< List of active libwebsocket connections in server mode (struct websocket_connection) */ - struct list destinations; /**< List of struct lws_client_connect_info to connect to in client mode. */ + struct list connections; /**< List of active libwebsocket connections in server mode (struct websocket_connection). */ + struct list destinations; /**< List of websocket servers connect to in client mode (struct websocket_destination). */ struct pool pool; + struct queue queue; /**< For samples which are received from WebSockets a */ - struct queue queue_tx; /**< For samples which are sent to WebSockets */ - struct queue queue_rx; /**< For samples which are received from WebSockets */ - - qptr_t sent; - qptr_t received; - - int shutdown; + int id; /**< The index of this node */ }; struct websocket_connection { enum { WEBSOCKET_ESTABLISHED, WEBSOCKET_ACTIVE, + WEBSOCKET_SHUTDOWN, WEBSOCKET_CLOSED } state; struct node *node; struct path *path; + struct queue queue; /**< For samples which are sent to the WebSocket */ + struct lws *wsi; struct { char name[64]; char ip[64]; } peer; - - qptr_t sent; - qptr_t received; + + char *_name; }; +int websocket_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); + /** @see node_vtable::init */ -int websocket_init(int argc, char * argv[], config_setting_t *cfg); +int websocket_init(int argc, char *argv[], config_setting_t *cfg); /** @see node_vtable::deinit */ int websocket_deinit(); /** @see node_vtable::open */ -int websocket_open(struct node *n); +int websocket_start(struct node *n); /** @see node_vtable::close */ -int websocket_close(struct node *n); +int websocket_stop(struct node *n); /** @see node_vtable::close */ int websocket_destroy(struct node *n); @@ -82,4 +82,4 @@ int websocket_read(struct node *n, struct sample *smps[], unsigned cnt); /** @see node_vtable::write */ int websocket_write(struct node *n, struct sample *smps[], unsigned cnt); -#endif /** _WEBSOCKET_H_ @} */ \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/path.h b/include/villas/path.h index 178c1dcb2..640b6e2ee 100644 --- a/include/villas/path.h +++ b/include/villas/path.h @@ -2,16 +2,16 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC - */ + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + /** A path connects one input node to multiple output nodes (1-to-n). * * @addtogroup path Path * @{ - *********************************************************************************/ + */ -#ifndef _PATH_H_ -#define _PATH_H_ +#pragma once #include #include @@ -21,76 +21,62 @@ #include "hist.h" #include "node.h" #include "msg.h" -#include "hooks.h" #include "queue.h" #include "pool.h" +#include "stats.h" +#include "common.h" -/** The datastructure for a path. - * - * @todo Add support for multiple outgoing nodes - */ +/* Forward declarations */ +struct super_node; +struct hook_info; + +struct path_source +{ + struct node *node; + struct pool pool; + int samplelen; + pthread_t tid; +}; + +struct path_destination +{ + struct node *node; + struct queue queue; + int queuelen; + pthread_t tid; +}; + +/** The datastructure for a path. */ struct path { - enum { - PATH_INVALID, /**< Path is invalid. */ - PATH_CREATED, /**< Path has been created. */ - PATH_RUNNING, /**< Path is currently running. */ - PATH_STOPPED /**< Path has been stopped. */ - } state; /**< Path state */ + enum state state; /**< Path state. */ - struct node *in; /**< Pointer to the incoming node */ - - struct queue queue; /**< A ring buffer for all received messages (unmodified) */ - struct pool pool; /**< Memory pool for messages / samples. */ + /* Each path has a single source and multiple destinations */ + struct path_source *source; /**< Pointer to the incoming node */ + struct list destinations; /**< List of all outgoing nodes (struct path_destination). */ - struct list destinations; /**< List of all outgoing nodes */ - struct list hooks; /**< List of function pointers to hooks */ + struct list hooks; /**< List of function pointers to hooks. */ - int samplelen; /**< Maximum number of values per sample for this path. */ - int queuelen; /**< Size of sample queue for this path. */ - int enabled; /**< Is this path enabled */ - int tfd; /**< Timer file descriptor for fixed rate sending */ - double rate; /**< Send messages with a fixed rate over this path */ + int enabled; /**< Is this path enabled. */ + int reverse; /**< This path as a matching reverse path. */ - pthread_t recv_tid; /**< The thread id for this path */ - pthread_t sent_tid; /**< A second thread id for fixed rate sending thread */ - - config_setting_t *cfg; /**< A pointer to the libconfig object which instantiated this path */ + pthread_t tid; /**< The thread id for this path. */ char *_name; /**< Singleton: A string which is used to print this path to screen. */ - /** The following fields are mostly managed by hook_ functions @{ */ + struct stats *stats; /**< Statistic counters. This is a pointer to the statistic hooks private data. */ - struct { - struct hist owd; /**< Histogram for one-way-delay (OWD) of received messages */ - struct hist gap_msg; /**< Histogram for inter message timestamps (as sent by remote) */ - struct hist gap_recv; /**< Histogram for inter message arrival time (as seen by this instance) */ - struct hist gap_seq; /**< Histogram of sequence number displacement of received messages */ - } hist; - - /* Statistic counters */ - uintmax_t invalid; /**< Counter for invalid messages */ - uintmax_t skipped; /**< Counter for skipped messages due to hooks */ - uintmax_t dropped; /**< Counter for dropped messages due to reordering */ - uintmax_t overrun; /**< Counter of overruns for fixed-rate sending */ - - /** @} */ + struct super_node *super_node; /**< The super node this path belongs to. */ + config_setting_t *cfg; /**< A pointer to the libconfig object which instantiated this path. */ }; -/** Create a path by allocating dynamic memory. */ -void path_init(struct path *p); +/** Initialize internal data structures. */ +int path_init(struct path *p, struct super_node *sn); -/** Destroy path by freeing dynamically allocated memory. - * - * @param i A pointer to the path structure. - */ -void path_destroy(struct path *p); +int path_init2(struct path *p); -/** Initialize pool queue and hooks. - * - * Should be called after path_init() and before path_start(). - */ -int path_prepare(struct path *p); +/** Check if path configuration is proper. */ +int path_check(struct path *p); /** Start a path. * @@ -110,6 +96,12 @@ int path_start(struct path *p); */ int path_stop(struct path *p); +/** Destroy path by freeing dynamically allocated memory. + * + * @param i A pointer to the path structure. + */ +int path_destroy(struct path *p); + /** Show some basic statistics for a path. * * @param p A pointer to the path structure. @@ -125,7 +117,31 @@ void path_print_stats(struct path *p); */ const char * path_name(struct path *p); +/** Reverse a path */ +int path_reverse(struct path *p, struct path *r); + /** Check if node is used as source or destination of a path. */ int path_uses_node(struct path *p, struct node *n); -#endif /** _PATH_H_ @} */ +/** Parse a single path and add it to the global configuration. + * + * @param cfg A libconfig object pointing to the path + * @param p Pointer to the allocated memory for this path + * @param nodes A linked list of all existing nodes + * @retval 0 Success. Everything went well. + * @retval <0 Error. Something went wrong. + */ +int path_parse(struct path *p, config_setting_t *cfg, struct list *nodes); + +/** Conditionally execute the hooks + * + * @param p A pointer to the path structure. + * @param when Which type of hooks should be executed? + * @param smps An array to of (cnt) pointers to msgs. + * @param cnt The size of the sample array. + * @retval 0 All registred hooks for the specified type have been executed successfully. + * @retval <0 On of the hook functions signalized, that the processing should be aborted; message should be skipped. + */ +int path_run_hooks(struct path *p, int when, struct sample *smps[], size_t cnt); + +/** @} */ \ No newline at end of file diff --git a/include/villas/plugin.h b/include/villas/plugin.h new file mode 100644 index 000000000..70bfc8067 --- /dev/null +++ b/include/villas/plugin.h @@ -0,0 +1,78 @@ +/** Loadable / plugin support. + * + * @file + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#pragma once + +#include "hook.h" +#include "api.h" +#include "common.h" +#include "utils.h" + +#include "fpga/ip.h" + +#include "nodes/cbuilder.h" + +#define REGISTER_PLUGIN(p) \ +__attribute__((constructor)) static void UNIQUE(__ctor)() { \ + list_push(&plugins, p); \ +} \ +__attribute__((destructor)) static void UNIQUE(__dtor)() { \ + list_remove(&plugins, p); \ +} + +extern struct list plugins; + +enum plugin_type { + PLUGIN_TYPE_HOOK, + PLUGIN_TYPE_NODE, + PLUGIN_TYPE_API, + PLUGIN_TYPE_FPGA_IP, + PLUGIN_TYPE_MODEL_CBUILDER +}; + +struct plugin { + char *name; + char *description; + void *handle; + char *path; + + enum plugin_type type; + + enum state state; + + int (*load)(struct plugin *p); + int (*unload)(struct plugin *p); + + union { + struct api_ressource api; + struct node_type node; + struct fpga_ip_type ip; + struct hook_type hook; + struct cbuilder_model cb; + }; +}; + +/** Return a pointer to the plugin structure */ +#define plugin(vt) ((struct plugin *) ((char *) (vt) - offsetof(struct plugin, api))) + +#define plugin_name(vt) plugin(vt)->name +#define plugin_description(vt) plugin(vt)->description + +int plugin_init(struct plugin *p); + +int plugin_destroy(struct plugin *p); + +int plugin_parse(struct plugin *p, config_setting_t *cfg); + +int plugin_load(struct plugin *p); + +int plugin_unload(struct plugin *p); + +void plugin_dump(enum plugin_type type); + +/** Find registered and loaded plugin with given name and type. */ +struct plugin * plugin_lookup(enum plugin_type type, const char *name); \ No newline at end of file diff --git a/include/villas/pool.h b/include/villas/pool.h index 38b017a7f..f8fef235f 100644 --- a/include/villas/pool.h +++ b/include/villas/pool.h @@ -4,15 +4,16 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC - */ + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ -#ifndef _POOL_H_ -#define _POOL_H_ +#pragma once +#include #include #include "queue.h" +#include "common.h" #include "memory.h" /** A thread-safe memory pool */ @@ -20,6 +21,8 @@ struct pool { void *buffer; /**< Address of the underlying memory area */ const struct memtype *mem; + enum state state; + size_t len; /**< Length of the underlying memory area */ size_t blocksz; /**< Length of a block in bytes */ @@ -30,19 +33,32 @@ struct pool { #define INLINE static inline __attribute__((unused)) -/** Initiazlize a pool */ +/** Initiazlize a pool + * + * @param[inout] p The pool data structure. + * @param[in] cnt The total number of blocks which are reserverd by this pool. + * @param[in] blocksz The size in bytes per block. + * @param[in] mem The type of memory which should be used for this pool. + * @retval 0 The pool has been successfully initialized. + * @retval <>0 There was an error during the pool initialization. + */ int pool_init(struct pool *p, size_t cnt, size_t blocksz, const struct memtype *mem); /** Destroy and release memory used by pool. */ int pool_destroy(struct pool *p); -/** Pop cnt values from the stack an place them in the array blocks */ +/** Pop up to \p cnt values from the stack an place them in the array \p blocks. + * + * @return The number of blocks actually retrieved from the pool. + * This number can be smaller than the requested \p cnt blocks + * in case the pool currently holds less than \p cnt blocks. + */ INLINE ssize_t pool_get_many(struct pool *p, void *blocks[], size_t cnt) { return queue_pull_many(&p->queue, blocks, cnt); } -/** Push cnt values which are giving by the array values to the stack. */ +/** Push \p cnt values which are giving by the array values to the stack. */ INLINE ssize_t pool_put_many(struct pool *p, void *blocks[], size_t cnt) { return queue_push_many(&p->queue, blocks, cnt); @@ -59,6 +75,4 @@ INLINE void * pool_get(struct pool *p) INLINE int pool_put(struct pool *p, void *buf) { return queue_push(&p->queue, buf); -} - -#endif /* _POOL_H_ */ \ No newline at end of file +} \ No newline at end of file diff --git a/include/villas/queue.h b/include/villas/queue.h index 40baf1f17..b68f72c76 100644 --- a/include/villas/queue.h +++ b/include/villas/queue.h @@ -4,7 +4,7 @@ * http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue * * @author Steffen Vogel - * @copyright 2016 Steffen Vogel + * @copyright 2017 Steffen Vogel * @license BSD 2-Clause License * * All rights reserved. @@ -29,21 +29,27 @@ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ + *********************************************************************************/ -#ifndef _MPMC_QUEUE_H_ -#define _MPMC_QUEUE_H_ +#pragma once +#include #include #include -#include "memory.h" +#include "common.h" + +/* Forward declarations */ +struct memtype; #define CACHELINE_SIZE 64 typedef char cacheline_pad_t[CACHELINE_SIZE]; +/** A lock-free multiple-producer, multiple-consumer (MPMC) queue. */ struct queue { cacheline_pad_t _pad0; /**< Shared area: all threads read */ + + enum state state; struct memtype const * mem; size_t buffer_mask; @@ -52,15 +58,15 @@ struct queue { void *data; } *buffer; - cacheline_pad_t _pad1; /**> Producer area: only producers read & write */ + cacheline_pad_t _pad1; /**< Producer area: only producers read & write */ - atomic_size_t tail; /**> Queue tail pointer */ + atomic_size_t tail; /**< Queue tail pointer */ - cacheline_pad_t _pad2; /**> Consumer area: only consumers read & write */ + cacheline_pad_t _pad2; /**< Consumer area: only consumers read & write */ - atomic_size_t head; /**> Queue head pointer */ + atomic_size_t head; /**< Queue head pointer */ - cacheline_pad_t _pad3; /**> @todo Why needed? */ + cacheline_pad_t _pad3; /**< @todo Why needed? */ }; /** Initialize MPMC queue */ @@ -80,8 +86,17 @@ int queue_push(struct queue *q, void *ptr); int queue_pull(struct queue *q, void **ptr); +/** Enqueue up to \p cnt pointers of the \p ptr array into the queue. + * + * @return The number of pointers actually enqueued. + * This number can be smaller then \p cnt in case the queue is filled. + */ int queue_push_many(struct queue *q, void *ptr[], size_t cnt); -int queue_pull_many(struct queue *q, void *ptr[], size_t cnt); - -#endif /* _MPMC_QUEUE_H_ */ \ No newline at end of file +/** Dequeue up to \p cnt pointers from the queue and place them into the \p ptr array. + * + * @return The number of pointers actually dequeued. + * This number can be smaller than \p cnt in case the queue contained less than + * \p cnt elements. + */ +int queue_pull_many(struct queue *q, void *ptr[], size_t cnt); \ No newline at end of file diff --git a/include/villas/sample.h b/include/villas/sample.h index 51cc1315b..b7c7908d5 100644 --- a/include/villas/sample.h +++ b/include/villas/sample.h @@ -2,11 +2,10 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC - */ + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ -#ifndef _SAMPLE_H_ -#define _SAMPLE_H_ +#pragma once #include #include @@ -27,13 +26,9 @@ struct pool; /** The offset to the beginning of the data section. */ #define SAMPLE_DATA_OFFSET(smp) ((char *) (smp) + offsetof(struct sample, data)) -/** These flags define the format which is used by sample_fscan() and sample_fprint(). */ -enum sample_flags { - SAMPLE_NANOSECONDS = 1, - SAMPLE_OFFSET = 2, - SAMPLE_SEQUENCE = 4, - SAMPLE_VALUES = 8, - SAMPLE_ALL = 16-1 +enum sample_data_format { + SAMPLE_DATA_FORMAT_FLOAT= 0, + SAMPLE_DATA_FORMAT_INT = 1 }; struct sample { @@ -43,8 +38,7 @@ struct sample { atomic_int refcnt; /**< Reference counter. */ struct pool *pool; /**< This sample is belong to this memory pool. */ - - int endian; /**< Endianess of data in the sample. */ + struct node *source; /**< The node from which this sample originates. */ /** All timestamps are seconds / nano seconds after 1.1.1970 UTC */ struct { @@ -52,16 +46,23 @@ struct sample { struct timespec received; /**< The point in time when this data was received. */ struct timespec sent; /**< The point in time this data was send for the last time. */ } ts; + + uint64_t format; /**< A long bitfield indicating the number representation of the first 64 values in sample::data[] */ /** The values. */ union { - float f; /**< Floating point values (note msg::endian) */ - uint32_t i; /**< Integer values (note msg::endian) */ - } data[]; + float f; /**< Floating point values. */ + uint32_t i; /**< Integer values. */ + } data[]; /**< Data is in host endianess! */ }; -/** Request \p cnt samples from memory pool \p p and initialize them. */ -int sample_get_many(struct pool *p, struct sample *smps[], int cnt); +/** Request \p cnt samples from memory pool \p p and initialize them. + * This will leave the reference count of the sample to zero. + * Use the sample_get() function to increase it. */ +int sample_alloc(struct pool *p, struct sample *smps[], int cnt); + +/** Release an array of samples back to their pools */ +void sample_free(struct sample *smps[], int cnt); /** Increase reference count of sample */ int sample_get(struct sample *s); @@ -69,44 +70,8 @@ int sample_get(struct sample *s); /** Decrease reference count and release memory if last reference was held. */ int sample_put(struct sample *s); -/** Print a sample in human readable form to a file stream. - * - * @param buf A character buffer of len bytes. - * @param len The size of buf. - * @param m A pointer to the sample. - * @param flags See sample_flags. - * @return Number of bytes written to buf. - */ -int sample_print(char *buf, size_t len, struct sample *s, int flags); +/** Set number representation for a single value of a sample. */ +int sample_get_data_format(struct sample *s, int idx); -/** Read a sample from a character buffer. - * - * @param line A string which should be parsed. - * @param s A pointer to the sample. - * @param flags et SAMPLE_* flags for each component found in sample if not NULL. See sample_flags. - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ -int sample_scan(const char *line, struct sample *s, int *fl); - -/** Print a sample in human readable form to a file stream. - * - * @see sample_print() - * @param f The file handle from fopen() or stdout, stderr. - * @param s A pointer to the sample. - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ -int sample_fprint(FILE *f, struct sample *s, int flags); - -/** Read a sample from a file stream. - * - * @see sample_scan() - * @param f The file handle from fopen() or stdin. - * @param s A pointer to the sample. - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ -int sample_fscan(FILE *f, struct sample *s, int *flags); - -#endif /* _SAMPLE_H_ */ \ No newline at end of file +/** Get number representation for a single value of a sample. */ +int sample_set_data_format(struct sample *s, int idx, enum sample_data_format fmt); \ No newline at end of file diff --git a/include/villas/sample_io.h b/include/villas/sample_io.h new file mode 100644 index 000000000..4e14fe809 --- /dev/null +++ b/include/villas/sample_io.h @@ -0,0 +1,83 @@ +/** Read / write sample data in different formats. + * + * @file + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#pragma once + +#include +#include + +/* Forward declarations */ +struct sample; + +enum sample_io_format { + SAMPLE_IO_FORMAT_VILLAS, + SAMPLE_IO_FORMAT_JSON, + SAMPLE_IO_FORMAT_HDF5, + SAMPLE_IO_FORMAT_COMTRADE +}; + +/** These flags define the format which is used by sample_io_fscan() and sample_io_fprint(). */ +enum sample_flags { + SAMPLE_IO_NANOSECONDS = (1 << 0), + SAMPLE_IO_OFFSET = (1 << 1), + SAMPLE_IO_SEQUENCE = (1 << 2), + SAMPLE_IO_VALUES = (1 << 3), + SAMPLE_IO_ALL = 16-1 +}; + +/* Not implemented yet */ +#if 0 +struct sample_io_handle { + enum sample_io_format format; + int flags + + FILE *file; + + struct list fields; +}; + +int sample_io_init(struct sample_io *io, enum sample_io_format fmt, char *mode, int flags); + +int sample_io_destroy(struct sample_io *io); + +int sample_io_open(struct sample_io *io); + +int sample_io_close(struct sample_io *io); + +int sample_io_write(struct sample_io *io, struct sample *smps[], size_t cnt); + +int sample_io_read(struct sample_io *io, struct sample *smps[], size_t cnt); + +int sample_io_eof(struct sample_io *io); +int sample_io_rewind(struct sample_io *io); +#endif + +/* Lowlevel interface */ + +int sample_io_fprint(FILE *f, struct sample *s, enum sample_io_format fmt, int flags); + +int sample_io_fscan(FILE *f, struct sample *s, enum sample_io_format fmt, int *flags); + +/* VILLASnode human readable format */ + +int sample_io_villas_print(char *buf, size_t len, struct sample *s, int flags); + +int sample_io_villas_scan(const char *line, struct sample *s, int *fl); + +int sample_io_villas_fprint(FILE *f, struct sample *s, int flags); + +int sample_io_villas_fscan(FILE *f, struct sample *s, int *flags); + +/* JSON format */ + +int sample_io_json_pack(json_t **j, struct sample *s, int flags); + +int sample_io_json_unpack(json_t *j, struct sample *s, int *flags); + +int sample_io_json_fprint(FILE *f, struct sample *s, int flags); + +int sample_io_json_fscan(FILE *f, struct sample *s, int *flags); diff --git a/include/villas/stats.h b/include/villas/stats.h new file mode 100644 index 000000000..d72c2aa86 --- /dev/null +++ b/include/villas/stats.h @@ -0,0 +1,79 @@ +/** Statistic collection. + * + * @file + * @author Steffen Vogel + * @copyright 2014-2016, 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. + */ + +#ifndef _STATS_H_ +#define _STATS_H_ + +#include + +#ifdef WITH_JANSSON + #include +#endif + +#include "hist.h" + +/* Forward declarations */ +struct sample; +struct path; +struct node; + +enum stats_format { + STATS_FORMAT_HUMAN, + STATS_FORMAT_JSON, + STATS_FORMAT_MATLAB +}; + +enum stats_id { + STATS_SKIPPED, /**< Counter for skipped messages due to hooks */ + STATS_DROPPED, /**< Counter for dropped messages due to reordering */ + STATS_GAP_SEQUENCE, /**< Histogram of sequence number displacement of received messages */ + STATS_GAP_SAMPLE, /**< Histogram for inter message timestamps (as sent by remote) */ + STATS_GAP_RECEIVED, /**< Histogram for inter message arrival time (as seen by this instance) */ + STATS_OWD, /**< Histogram for one-way-delay (OWD) of received messages */ + STATS_COUNT /**< Just here to have an updated number of statistics */ +}; + +struct stats_delta { + double values[STATS_COUNT]; + + int update; /**< Bitmask of stats_id. Only those which are masked will be updated */ + struct sample *last; +}; + +struct stats { + struct hist histograms[STATS_COUNT]; + + struct stats_delta *delta; +}; + +int stats_init(struct stats *s); + +void stats_destroy(struct stats *s); + +void stats_update(struct stats_delta *s, enum stats_id id, double val); + +void stats_collect(struct stats_delta *s, struct sample *smps[], size_t cnt); + +int stats_commit(struct stats *s, struct stats_delta *d); + +#ifdef WITH_JANSSON +json_t * stats_json(struct stats *s); +#endif + +void stats_reset(struct stats *s); + +void stats_print_header(); + +void stats_print_periodic(struct stats *s, FILE *f, enum stats_format fmt, int verbose, struct path *p); + +void stats_print(struct stats *s, FILE *f, enum stats_format fmt, int verbose); + +void stats_send(struct stats *s, struct node *n); + +#endif /* _STATS_H_ */ \ No newline at end of file diff --git a/include/villas/super_node.h b/include/villas/super_node.h new file mode 100644 index 000000000..52026dd7b --- /dev/null +++ b/include/villas/super_node.h @@ -0,0 +1,80 @@ +/** Configuration file parser. + * + * The server program is configured by a single file. + * This config file is parsed with a third-party library: + * libconfig http://www.hyperrealm.com/libconfig/ + * + * @file + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#pragma once + +#include + +#include "list.h" +#include "api.h" +#include "web.h" +#include "log.h" +#include "common.h" + +/** Global configuration */ +struct super_node { + int priority; /**< Process priority (lower is better) */ + int affinity; /**< Process affinity of the server and all created threads */ + int hugepages; /**< Number of hugepages to reserve. */ + double stats; /**< Interval for path statistics. Set to 0 to disable them. */ + + struct list nodes; + struct list paths; + struct list plugins; + + struct log log; + struct api api; + struct web web; + + struct { + int argc; + char **argv; + } cli; + + enum state state; + + config_t cfg; /**< Pointer to configuration file */ + json_t *json; /**< JSON representation of the same config. */ +}; + +/* Compatibility with libconfig < 1.5 */ +#if (LIBCONFIG_VER_MAJOR <= 1) && (LIBCONFIG_VER_MINOR < 5) + #define config_setting_lookup config_lookup_from +#endif + +/** Inititalize configuration object before parsing the configuration. */ +int super_node_init(struct super_node *sn); + +/** Wrapper for super_node_parse() */ +int super_node_parse_cli(struct super_node *sn, int argc, char *argv[]); + +/** Wrapper for super_node_parse() */ +int super_node_parse_uri(struct super_node *sn, const char *uri); + +/** Parse super-node configuration. + * + * @param sn The super-node datastructure to fill. + * @param cfg A libconfig setting object. + * @retval 0 Success. Everything went well. + * @retval <0 Error. Something went wrong. + */ +int super_node_parse(struct super_node *sn, config_setting_t *cfg); + +/** Check validity of super node configuration. */ +int super_node_check(struct super_node *sn); + +/** Initialize after parsing the configuration file. */ +int super_node_start(struct super_node *sn); + +int super_node_stop(struct super_node *sn); + +/** Desctroy configuration object. */ +int super_node_destroy(struct super_node *sn); \ No newline at end of file diff --git a/include/villas/timing.h b/include/villas/timing.h index d3e083942..5872a7d40 100644 --- a/include/villas/timing.h +++ b/include/villas/timing.h @@ -2,11 +2,10 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ -#ifndef _TIME_H_ -#define _TIME_H_ +#pragma once #include #include @@ -50,6 +49,4 @@ double time_delta(struct timespec *start, struct timespec *end); double time_to_double(struct timespec *ts); /** Convert double containing seconds after 1970 to timespec. */ -struct timespec time_from_double(double secs); - -#endif /* _TIMING_H_ */ \ No newline at end of file +struct timespec time_from_double(double secs); \ No newline at end of file diff --git a/include/villas/utils.h b/include/villas/utils.h index 5e8933222..aa76bc048 100644 --- a/include/villas/utils.h +++ b/include/villas/utils.h @@ -2,18 +2,20 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ -#ifndef _UTILS_H_ -#define _UTILS_H_ +#pragma once #include #include #include #include +#include #include +#include + #include "log.h" #ifdef __GNUC__ @@ -53,6 +55,13 @@ #define ALIGN_MASK(x, m) (((uintptr_t) (x) + (m)) & ~(m)) #define IS_ALIGNED(x, a) (ALIGN(x, a) == (uintptr_t) x) +#define SWAP(x,y) do { \ + __auto_type _x = x; \ + __auto_type _y = y; \ + x = _y; \ + y = _x; \ +} while(0) + /** Round-up integer division */ #define CEIL(x, y) (((x) + (y) - 1) / (y)) @@ -92,7 +101,6 @@ #define BIT(nr) (1UL << (nr)) /* Forward declarations */ -struct settings; struct timespec; /** Print copyright message to screen. */ @@ -168,6 +176,7 @@ char * cpulist_create(char *str, size_t len, cpu_set_t *set); json_t * config_to_json(config_setting_t *cfg); #endif +int json_to_config(json_t *json, config_setting_t *parent); /** Allocate and initialize memory. */ void * alloc(size_t bytes); @@ -200,13 +209,7 @@ int version_parse(const char *s, struct version *v); #endif /** Fill buffer with random data */ -int read_random(char *buf, size_t len); - -/** Hexdump bytes */ -void printb(void *mem, size_t len); - -/** Hexdump 32-bit dwords */ -void printdw(void *mem, size_t len); +ssize_t read_random(char *buf, size_t len); /** Get CPU timestep counter */ __attribute__((always_inline)) static inline uint64_t rdtsc() @@ -225,7 +228,8 @@ __attribute__((always_inline)) static inline uint64_t rdtsc() /** Get log2 of long long integers */ static inline int log2i(long long x) { - assert(x > 0); + if (x == 0) + return 1; return sizeof(x) * 8 - __builtin_clzll(x) - 1; } @@ -233,4 +237,12 @@ static inline int log2i(long long x) { /** Sleep with rdtsc */ void rdtsc_sleep(uint64_t nanosecs, uint64_t start); -#endif /* _UTILS_H_ */ \ No newline at end of file +/** Register a exit callback for program termination (SIGINT / SIGKILL). */ +void signals_init(void (*cb)(int signal, siginfo_t *sinfo, void *ctx)); + +/** Calculate SHA1 hash of complete file \p f and place it into \p sha1. + * + * @param sha1[out] Must be SHA_DIGEST_LENGTH (20) in size. + * @retval 0 Everything was okay. + */ +int sha1sum(FILE *f, unsigned char *sha1); diff --git a/include/villas/web.h b/include/villas/web.h new file mode 100644 index 000000000..072186946 --- /dev/null +++ b/include/villas/web.h @@ -0,0 +1,45 @@ +/** LWS-releated functions. + * + * @file + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#pragma once + +#include "common.h" + +/* Forward declarations */ +struct api; + +struct web { + struct api *api; + + enum state state; + + struct lws_context *context; /**< The libwebsockets server context. */ + struct lws_vhost *vhost; /**< The libwebsockets vhost. */ + + int port; /**< Port of the build in HTTP / WebSocket server. */ + const char *htdocs; /**< The root directory for files served via HTTP. */ + const char *ssl_cert; /**< Path to the SSL certitifcate for HTTPS / WSS. */ + const char *ssl_private_key; /**< Path to the SSL private key for HTTPS / WSS. */ +}; + +/** Initialize the web interface. + * + * The web interface is based on the libwebsockets library. + */ +int web_init(struct web *w, struct api *a); + +int web_destroy(struct web *w); + +int web_start(struct web *w); + +int web_stop(struct web *w); + +/** Parse HTTPd and WebSocket related options */ +int web_parse(struct web *w, config_setting_t *lcs); + +/** libwebsockets service routine. Call periodically */ +int web_service(struct web *w); \ No newline at end of file diff --git a/include/villas/webmsg_format.h b/include/villas/webmsg_format.h new file mode 100644 index 000000000..19b600de6 --- /dev/null +++ b/include/villas/webmsg_format.h @@ -0,0 +1,101 @@ +/** Binary websocket message format + * + * @file + * @author Steffen Vogel + * @copyright 2014-2016, 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. + *********************************************************************************/ + +#pragma once + +#include + +#include "msg_format.h" + +#ifdef __linux__ + #define _BSD_SOURCE 1 + #include +#elif defined(__PPC__) /* Xilinx toolchain */ + #include +#endif + +/** The current version number for the message format */ +#define WEBMSG_VERSION 1 + +/** @todo Implement more message types */ +#define WEBMSG_TYPE_DATA 0 /**< Message contains float values */ +#define WEBMSG_TYPE_START 1 /**< Message marks the beginning of a new simulation case */ +#define WEBMSG_TYPE_STOP 2 /**< Message marks the end of a simulation case */ + +#define WEBMSG_ENDIAN_LITTLE 0 /**< Message values are in little endian format (float too!) */ +#define WEBMSG_ENDIAN_BIG 1 /**< Message values are in bit endian format */ + +#if BYTE_ORDER == LITTLE_ENDIAN + #define WEBMSG_ENDIAN_HOST MSG_ENDIAN_LITTLE +#elif BYTE_ORDER == BIG_ENDIAN + #define WEBMSG_ENDIAN_HOST MSG_ENDIAN_BIG +#else + #error "Unknown byte order!" +#endif + +/** The total size in bytes of a message */ +#define WEBMSG_LEN(values) (sizeof(struct webmsg) + MSG_DATA_LEN(values)) + +/** The length of \p values values in bytes. */ +#define WEBMSG_DATA_LEN(values) (sizeof(float) * (values)) + +/** The offset to the first data value in a message. */ +#define WEBMSG_DATA_OFFSET(msg) ((char *) (msg) + offsetof(struct webmsg, data)) + +/** Initialize a message with default values */ +#define WEBMSG_INIT(len, seq) (struct webmsg) {\ + .version = WEBMSG_VERSION, \ + .type = WEBMSG_TYPE_DATA, \ + .endian = WEBMSG_ENDIAN_HOST, \ + .length = len, \ + .sequence = seq \ +} + +/** The timestamp of a message in struct timespec format */ +#define WEBMSG_TS(msg) (struct timespec) {\ + .tv_sec = (msg)->ts.sec, \ + .tv_nsec = (msg)->ts.nsec \ +} + +/** This message format is used by all clients + * + * @diafile msg_format.dia + **/ +struct webmsg +{ +#if BYTE_ORDER == BIG_ENDIAN + unsigned version: 4; /**< Specifies the format of the remaining message (see MGS_VERSION) */ + unsigned type : 2; /**< Data or control message (see MSG_TYPE_*) */ + unsigned endian : 1; /**< Specifies the byteorder of the message (see MSG_ENDIAN_*) */ + unsigned rsvd1 : 1; /**< Reserved bits */ +#elif BYTE_ORDER == LITTLE_ENDIAN + unsigned rsvd1 : 1; /**< Reserved bits */ + unsigned endian : 1; /**< Specifies the byteorder of the message (see MSG_ENDIAN_*) */ + unsigned type : 2; /**< Data or control message (see MSG_TYPE_*) */ + unsigned version: 4; /**< Specifies the format of the remaining message (see MGS_VERSION) */ +#endif + + uint8_t id; /**< The node index from / to which this sample received / sent to. + * Corresponds to the index of the node in the http://localhost/nodes.json array. */ + + uint16_t length; /**< The number of values in msg::data[]. Endianess is specified in msg::endian. */ + uint32_t sequence; /**< The sequence number is incremented by one for consecutive messages. Endianess is specified in msg::endian. */ + + /** A timestamp per message. Endianess is specified in msg::endian. */ + struct { + uint32_t sec; /**< Seconds since 1970-01-01 00:00:00 */ + uint32_t nsec; /**< Nanoseconds of the current second. */ + } ts; + + /** The message payload. Endianess is specified in msg::endian. */ + union { + float f; /**< Floating point values (note msg::endian) */ + uint32_t i; /**< Integer values (note msg::endian) */ + } data[]; +} __attribute__((packed)); \ No newline at end of file diff --git a/lib/Makefile.inc b/lib/Makefile.inc index 03a8e32e1..6b2408e4e 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -1,18 +1,26 @@ -# Libraries -LIBS = $(BUILDDIR)/libvillas.so +LIB_NAME = libvillas +LIB_ABI_VERSION = 1 + +LIB = $(BUILDDIR)/$(LIB_NAME).so # Object files for libvillas LIB_SRCS = $(addprefix lib/nodes/, file.c cbuilder.c) \ $(addprefix lib/kernel/, kernel.c rt.c) \ - $(addprefix lib/, sample.c path.c node.c hooks.c \ - log.c utils.c cfg.c hist.c timing.c pool.c list.c \ - queue.c memory.c \ - ) \ - $(wildcard lib/hooks/*.c) \ + $(addprefix lib/, sample.c path.c node.c hook.c \ + log.c utils.c super_node.c hist.c timing.c pool.c \ + list.c queue.c memory.c advio.c web.c api.c \ + plugin.c node_type.c stats.c mapping.c sample_io.c\ + ) LIB_CFLAGS = $(CFLAGS) -fPIC LIB_LDFLAGS = -shared -LIB_LDLIBS = $(LDLIBS) -ldl -lrt +LIB_LDLIBS = $(LDLIBS) -ldl -lrt -Wl,-soname,$(LIB_NAME).so.$(LIB_ABI_VERSION) + +-include lib/hooks/Makefile.inc +-include lib/apis/Makefile.inc +-include lib/fpga/Makefile.inc + +LIB_PKGS = openssl ######## Node types ######## @@ -23,8 +31,6 @@ ifeq ($(shell pkg-config libnl-route-3.0; echo $$?),0) LIB_SRCS += $(addprefix lib/kernel/, nl.c tc.c if.c) LIB_SRCS += $(addprefix lib/, msg.c) LIB_PKGS += libnl-route-3.0 -else - $(error Missing dependecy: libnl-3) endif endif @@ -33,10 +39,7 @@ ifndef WITHOUT_FPGA ifeq ($(shell pkg-config libxil; echo $$?),0) LIB_SRCS += $(addprefix lib/nodes/, fpga.c) LIB_SRCS += $(addprefix lib/kernel/, pci.c vfio.c) - LIB_SRCS += $(wildcard lib/fpga/*.c) PKGS += libxil -else - $(error Missing dependecy: libxil) endif endif @@ -45,8 +48,6 @@ ifndef WITHOUT_NGSI ifeq ($(shell pkg-config libcurl jansson; echo $$?),0) LIB_SRCS += lib/nodes/ngsi.c LIB_PKGS += libcurl jansson -else - $(error Missing dependecies: libjansson) endif endif @@ -55,8 +56,6 @@ ifndef WITHOUT_WEBSOCKETS ifeq ($(shell pkg-config libwebsockets jansson; echo $$?),0) LIB_SRCS += lib/nodes/websocket.c LIB_PKGS += libwebsockets jansson -else - $(error Missing dependecies: libwebsockets or libjansson) endif endif @@ -73,36 +72,32 @@ ifneq (,$(wildcard thirdparty/opal/include/AsyncApi.h)) CFLAGS += -m32 LDFLAGS += -m32 BUILDDIR := $(BUILDDIR)32 -else - $(error Missing dependecy: libOpalUtils libOpalAsyncApiCore) endif endif # Add flags by pkg-config -LIB_CFLAGS += $(addprefix -DWITH_, $(shell echo ${LIB_PKGS} | tr a-z- A-Z_ | tr -dc ' A-Z0-9_' )) LIB_CFLAGS += $(shell pkg-config --cflags ${LIB_PKGS}) LIB_LDLIBS += $(shell pkg-config --libs ${LIB_PKGS}) LIB_OBJS = $(patsubst %.c, $(BUILDDIR)/%.o, $(LIB_SRCS)) -lib: $(LIBS) - -# Compile -$(BUILDDIR)/lib/%.o: lib/%.c | $$(dir $$@) - $(CC) $(LIB_CFLAGS) -c $< -o $@ +lib: $(LIB) # Link -$(LIBS): $(LIB_OBJS) +$(LIB): $(LIB_OBJS) $(CC) $(LIB_LDFLAGS) -o $@ $^ $(LIB_LDLIBS) - + +# Compile +$(BUILDDIR)/lib/%.o: lib/%.c $(BUILDDIR)/defines | $$(dir $$@) + $(CC) $(LIB_CFLAGS) -c $< -o $@ + # Install install-lib: lib - install -m 0644 $(LIBS) $(PREFIX)/lib - install -m 0755 -d $(PREFIX)/include/villas/ - install -m 0644 include/villas/*.h $(PREFIX)/include/villas/ - ldconfig + install -m 0755 -D -T $(LIB) $(DESTDIR)$(PREFIX)/lib/$(LIB_NAME).so.$(LIB_ABI_VERSION) + install -m 0644 -D -t $(DESTDIR)$(PREFIX)/include/villas/ include/villas/*.h + ln -srf $(DESTDIR)$(PREFIX)/lib/$(LIB_NAME).so.$(LIB_ABI_VERSION) $(DESTDIR)$(PREFIX)/lib/$(LIB_NAME).so clean-lib: - rm -rf $(BUILDDIR)/lib $(LIBS) + rm -rf $(BUILDDIR)/lib $(LIB) -.PHONY: lib lib-tests lib-tests +.PHONY: lib install-lib clean-lib $(BUILDDIR)/lib/defines diff --git a/lib/advio.c b/lib/advio.c new file mode 100644 index 000000000..f2d942394 --- /dev/null +++ b/lib/advio.c @@ -0,0 +1,233 @@ +/** libcurl based advanced IO aka ADVIO. + * + * This example requires libcurl 7.9.7 or later. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "utils.h" +#include "config.h" +#include "advio.h" + +#define BAR_WIDTH 60 /**< How wide you want the progress meter to be. */ + +static int advio_xferinfo(void *p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) +{ + struct advio *af = (struct advio *) p; + double curtime = 0; + + curl_easy_getinfo(af->curl, CURLINFO_TOTAL_TIME, &curtime); + + // ensure that the file to be downloaded is not empty + // because that would cause a division by zero error later on + if (dltotal <= 0.0) + return 0; + + double frac = dlnow / dltotal; + + // part of the progressmeter that's already "full" + int dotz = round(frac * BAR_WIDTH); + + // create the "meter" + fprintf(stderr, "%3.0f%% in %f s (%" CURL_FORMAT_CURL_OFF_T " / %" CURL_FORMAT_CURL_OFF_T ") [", frac * 100, curtime, dlnow, dltotal); + + // part that's full already + int i = 0; + for ( ; i < dotz; i++) + fprintf(stderr, "="); + + // remaining part (spaces) + for ( ; i < BAR_WIDTH; i++) + fprintf(stderr, " "); + + // and back to line begin - do not forget the fflush to avoid output buffering problems! + fprintf(stderr, "]\r"); + fflush(stderr); + + return 0; +} + +AFILE * afopen(const char *uri, const char *mode) +{ + int ret; + + AFILE *af = alloc(sizeof(AFILE)); + + strncpy(af->mode, mode, sizeof(af->mode)); + + af->uri = strdup(uri); + if (!af->uri) + goto out2; + + af->file = tmpfile(); + if (!af->file) + goto out2; + + af->curl = curl_easy_init(); + if (!af->curl) + goto out1; + + /* Setup libcurl handle */ + curl_easy_setopt(af->curl, CURLOPT_DEFAULT_PROTOCOL, "file"); + curl_easy_setopt(af->curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(af->curl, CURLOPT_UPLOAD, 0L); + curl_easy_setopt(af->curl, CURLOPT_USERAGENT, USER_AGENT); + curl_easy_setopt(af->curl, CURLOPT_URL, uri); + curl_easy_setopt(af->curl, CURLOPT_WRITEDATA, af->file); + curl_easy_setopt(af->curl, CURLOPT_XFERINFOFUNCTION, advio_xferinfo); + curl_easy_setopt(af->curl, CURLOPT_XFERINFODATA, af); + curl_easy_setopt(af->curl, CURLOPT_NOPROGRESS, 0L); + + ret = adownload(af); + if (ret) + goto out0; + + return af; + +out0: curl_easy_cleanup(af->curl); +out1: fclose(af->file); +out2: free(af->uri); + free(af); + + return NULL; +} + +int afclose(AFILE *af) +{ + int ret; + + ret = afflush(af); + + curl_easy_cleanup(af->curl); + fclose(af->file); + + free(af->uri); + free(af); + + return ret; +} + +int afflush(AFILE *af) +{ + bool dirty; + unsigned char hash[SHA_DIGEST_LENGTH]; + + /* Check if fle was modified on disk by comparing hashes */ + sha1sum(af->file, hash); + dirty = memcmp(hash, af->hash, sizeof(hash)); + + if (dirty) + return aupload(af); + + return 0; +} + +int aupload(AFILE *af) +{ + CURLcode res; + long pos; + int ret; + + ret = fflush(af->file); + if (ret) + return ret; + + curl_easy_setopt(af->curl, CURLOPT_UPLOAD, 1L); + curl_easy_setopt(af->curl, CURLOPT_READDATA, af->file); + + pos = ftell(af->file); /* Remember old stream pointer */ + fseek(af->file, 0, SEEK_SET); + + res = curl_easy_perform(af->curl); + + fprintf(stderr, "\e[2K"); + fflush(stderr); /* do not continue in the same line as the progress bar */ + + fseek(af->file, pos, SEEK_SET); /* Restore old stream pointer */ + + if (res != CURLE_OK) + return -1; + + sha1sum(af->file, af->hash); + + return 0; +} + +int adownload(AFILE *af) +{ + CURLcode res; + long code; + int ret; + + fseek(af->file, 0, SEEK_SET); + + res = curl_easy_perform(af->curl); + + fprintf(stderr, "\e[2K"); + fflush(stderr); /* do not continue in the same line as the progress bar */ + + switch (res) { + case CURLE_OK: + curl_easy_getinfo(af->curl, CURLINFO_RESPONSE_CODE, &code); + switch (code) { + case 0: + case 200: goto exist; + case 404: goto notexist; + default: return -1; + } + + /* The following error codes indicate that the file does not exist + * Check the fopen mode to see if we should continue with an emoty file */ + case CURLE_FILE_COULDNT_READ_FILE: + case CURLE_TFTP_NOTFOUND: + case CURLE_REMOTE_FILE_NOT_FOUND: + goto notexist; + + /* If libcurl does not know the protocol, we will try it with the stdio */ + case CURLE_UNSUPPORTED_PROTOCOL: + af->file = fopen(af->uri, af->mode); + if (!af->file) + return -1; + + default: + error("Failed to fetch file: %s: %s\n", af->uri, curl_easy_strerror(res)); + return -1; + } + + +notexist: /* File does not exist */ + + /* According to mode the file must exist! */ + if (af->mode[1] != '+' || (af->mode[0] != 'w' && af->mode[0] != 'a')) { + errno = ENOENT; + return -1; + } + + /* If we receive a 404, we discard the already received error page + * and start with an empty file. */ + fflush(af->file); + ret = ftruncate(fileno(af->file), 0); + if (ret) + return ret; + +exist: /* File exists */ + if (af->mode[0] == 'a') + fseek(af->file, 0, SEEK_END); + else if (af->mode[0] == 'r' || af->mode[0] == 'w') + fseek(af->file, 0, SEEK_SET); + + sha1sum(af->file, af->hash); + + return 0; +} diff --git a/lib/api.c b/lib/api.c new file mode 100644 index 000000000..4722dd7db --- /dev/null +++ b/lib/api.c @@ -0,0 +1,295 @@ +/** REST-API-releated functions. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#include + +#include "plugin.h" +#include "api.h" +#include "log.h" +#include "config.h" + +#if JANSSON_VERSION_HEX < 0x020A00 +size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags) +{ + char *str; + size_t len; + + str = json_dumps(json, flags); + if (!str) + return 0; + + len = strlen(str) - 1; // not \0 terminated + if (buffer && len <= size) + memcpy(buffer, str, len); + + //free(str); + + return len; +} +#endif + +static int api_parse_request(struct api_buffer *b, json_t **req) +{ + json_error_t e; + + if (b->len <= 0) + return -1; + + *req = json_loadb(b->buf, b->len, JSON_DISABLE_EOF_CHECK, &e); + if (!*req) + return -1; + + if (e.position < b->len) { + void *dst = (void *) b->buf; + void *src = (void *) (b->buf + e.position); + + memmove(dst, src, b->len - e.position); + + b->len -= e.position; + } + + return 1; +} + +static int api_unparse_response(struct api_buffer *b, json_t *res) +{ + size_t len; + +retry: len = json_dumpb(res, b->buf + b->len, b->size - b->len, 0); + if (len > b->size - b->len) { + b->buf = realloc(b->buf, b->len + len); + b->len += len; + goto retry; + } + + return 0; +} + +int api_session_run_command(struct api_session *s, json_t *req, json_t **resp) +{ + int ret; + const char *rstr; + struct plugin *p; + + json_t *args; + + ret = json_unpack(req, "{ s: s, s: o }", + "command", &rstr, + "arguments", &args); + if (ret) + *resp = json_pack("{ s: s, s: d }", + "error", "invalid request", + "code", -1); + + p = plugin_lookup(PLUGIN_TYPE_API, rstr); + if (!p) + *resp = json_pack("{ s: s, s: d, s: s }", + "error", "command not found", + "code", -2, + "command", rstr); + + debug(LOG_API, "Running API request: %s with arguments: %s", p->name, json_dumps(args, 0)); + + ret = p->api.cb(&p->api, args, resp, s); + if (ret) + *resp = json_pack("{ s: s, s: d }", + "error", "command failed", + "code", ret); + + debug(LOG_API, "API request completed with code: %d and output: %s", ret, json_dumps(*resp, 0)); + + return 0; +} + +int api_ws_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) +{ + //struct api_session *s = (struct api_session *) user; + + switch (reason) { + default: + break; + } + + return 0; +} + +int api_http_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) +{ + int ret; + + struct api_session *s = (struct api_session *) user; + + switch (reason) { + case LWS_CALLBACK_ESTABLISHED: { + struct web *w = (struct web *) lws_context_user(lws_get_context(wsi)); + + if (w->api == NULL) + return -1; /** @todo return error message */ + + api_session_init(s, w->api, API_MODE_WS); + break; + } + + case LWS_CALLBACK_HTTP: { + struct web *w = (struct web *) lws_context_user(lws_get_context(wsi)); + + char *uri = (char *) in; + + /* Parse request URI */ + ret = sscanf(uri, "/api/v%d", (int *) &s->version); + if (ret != 1) + return -1; + + debug(LOG_API, "New REST API session initiated: version = %d", s->version); + + api_session_init(s, w->api, API_MODE_HTTP); + + /* Prepare HTTP response header */ + const char headers[] = "HTTP/1.1 200 OK\r\n" + "Content-type: application/json\r\n" + "User-agent: " USER_AGENT + "\r\n"; + + api_buffer_append(&s->response.headers, headers, sizeof(headers)); + + /* book us a LWS_CALLBACK_HTTP_WRITEABLE callback */ + lws_callback_on_writable(wsi); + + break; + } + + case LWS_CALLBACK_CLIENT_RECEIVE: + case LWS_CALLBACK_RECEIVE: + case LWS_CALLBACK_HTTP_BODY: { + api_buffer_append(&s->request.body, in, len); + + json_t *req, *resp; + while (api_parse_request(&s->request.body, &req) == 1) { + + api_session_run_command(s, req, &resp); + + api_unparse_response(&s->response.body, resp); + + debug(LOG_WEB, "Sending response: %s len=%zu", s->response.body.buf, s->response.body.len); + + lws_callback_on_writable(wsi); + } + + break; + } + + case LWS_CALLBACK_HTTP_BODY_COMPLETION: + s->completed = true; + break; + + case LWS_CALLBACK_SERVER_WRITEABLE: + case LWS_CALLBACK_HTTP_WRITEABLE: + /* We send headers only in HTTP mode */ + if (s->mode == API_MODE_HTTP) + api_buffer_send(&s->response.headers, wsi); + + api_buffer_send(&s->response.body, wsi); + + if (s->completed && s->response.body.len == 0) + return -1; + + break; + + default: + return 0; + } + + return 0; +} + +int api_buffer_send(struct api_buffer *b, struct lws *w) +{ + int sent; + + if (b->len <= 0) + return 0; + + sent = lws_write(w, (unsigned char *) b->buf, b->len, LWS_WRITE_HTTP_HEADERS); + if (sent > 0) { + memmove(b->buf, b->buf + sent, sent); + b->len -= sent; + } + + return sent; +} + +int api_buffer_append(struct api_buffer *b, const char *in, size_t len) +{ + b->buf = realloc(b->buf, b->len + len); + if (!b->buf) + return -1; + + memcpy(b->buf + b->len, in, len); + + b->len += len; + + return 0; +} + +int api_init(struct api *a, struct super_node *sn) +{ + info("Initialize API sub-system"); + + list_init(&a->sessions); + + a->super_node = sn; + a->state = STATE_INITIALIZED; + + return 0; +} + +int api_destroy(struct api *a) +{ + assert(a->state != STATE_STARTED); + + a->state = STATE_DESTROYED; + + return 0; +} + +int api_start(struct api *a) +{ + info("Starting API sub-system"); + + a->state = STATE_STARTED; + + return 0; +} + +int api_stop(struct api *a) +{ + info("Stopping API sub-system"); + + list_destroy(&a->sessions, (dtor_cb_t) api_session_destroy, false); + + a->state = STATE_STOPPED; + + return 0; +} + +int api_session_init(struct api_session *s, struct api *a, enum api_mode m) +{ + s->mode = m; + s->api = a; + + s->completed = false; + + s->request.body = + s->response.body = + s->response.headers = (struct api_buffer) { 0 }; + + return 0; +} + +int api_session_destroy(struct api_session *s) +{ + return 0; +} diff --git a/lib/apis/Makefile.inc b/lib/apis/Makefile.inc new file mode 100644 index 000000000..bfe1a1d4f --- /dev/null +++ b/lib/apis/Makefile.inc @@ -0,0 +1 @@ +LIB_SRCS += $(wildcard lib/apis/*.c) \ No newline at end of file diff --git a/lib/apis/config.c b/lib/apis/config.c new file mode 100644 index 000000000..ed1a78870 --- /dev/null +++ b/lib/apis/config.c @@ -0,0 +1,31 @@ +/** The "config" command + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + * This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + *********************************************************************************/ + +#include + +#include "api.h" +#include "utils.h" +#include "plugin.h" + +static int api_config(struct api_ressource *h, json_t *args, json_t **resp, struct api_session *s) +{ + config_setting_t *cfg_root = config_root_setting(&s->api->super_node->cfg); + + *resp = config_to_json(cfg_root); + + return 0; +} + +static struct plugin p = { + .name = "config", + .description = "retrieve current VILLASnode configuration", + .type = PLUGIN_TYPE_API, + .api.cb = api_config +}; + +REGISTER_PLUGIN(&p) \ No newline at end of file diff --git a/lib/apis/nodes.c b/lib/apis/nodes.c new file mode 100644 index 000000000..2487f8435 --- /dev/null +++ b/lib/apis/nodes.c @@ -0,0 +1,51 @@ +/** The "nodes" command + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + * This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + *********************************************************************************/ + +#include + +#include "plugin.h" +#include "api.h" +#include "node.h" +#include "utils.h" + +extern struct list nodes; + +static int api_nodes(struct api_ressource *r, json_t *args, json_t **resp, struct api_session *s) +{ + json_t *json_nodes = json_array(); + + for (size_t i = 0; i < list_length(&s->api->super_node->nodes); i++) { + struct node *n = list_at(&s->api->super_node->nodes, i); + + json_t *json_node = json_pack("{ s: s, s: i, s: i, s: i, s: i }", + "name", node_name_short(n), + "state", n->state, + "vectorize", n->vectorize, + "affinity", n->affinity + ); + + /* Add all additional fields of node here. + * This can be used for metadata */ + json_object_update(json_node, config_to_json(n->cfg)); + + json_array_append_new(json_nodes, json_node); + } + + *resp = json_nodes; + + return 0; +} + +static struct plugin p = { + .name = "nodes", + .description = "retrieve list of all known nodes", + .type = PLUGIN_TYPE_API, + .api.cb = api_nodes +}; + +REGISTER_PLUGIN(&p) \ No newline at end of file diff --git a/lib/apis/reload.c b/lib/apis/reload.c new file mode 100644 index 000000000..edabfc681 --- /dev/null +++ b/lib/apis/reload.c @@ -0,0 +1,25 @@ +/** The "reload" command + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + * This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + *********************************************************************************/ + +#include "plugin.h" +#include "api.h" + +/** @todo not implemented yet */ +static int api_reload(struct api_ressource *h, json_t *args, json_t **resp, struct api_session *s) +{ + return -1; +} + +static struct plugin p = { + .name = "reload", + .description = "restart VILLASnode with new configuration", + .type = PLUGIN_TYPE_API, + .api.cb = api_reload +}; + +REGISTER_PLUGIN(&p) \ No newline at end of file diff --git a/lib/boolean/boolean.l b/lib/boolean/boolean.l new file mode 100644 index 000000000..b88651fab --- /dev/null +++ b/lib/boolean/boolean.l @@ -0,0 +1,19 @@ +%{ +#include +#include + +#include "boolean.tab.h" // to get the token types that we return + +%} + +%option prefix="log_expression_" +%option noyywrap + +%% + +[ \t\n] ; // ignore whitespace +[&] ; //operators +[a-b]+ { log_expression_lval.token = strdup(log_expression_text); return TOKEN; } +[0-9]+ { log_expression_lval.constant = atoi(log_expression_text); return CONSTANT; } + +%% \ No newline at end of file diff --git a/lib/boolean/boolean.output b/lib/boolean/boolean.output new file mode 100644 index 000000000..ffbdf4992 --- /dev/null +++ b/lib/boolean/boolean.output @@ -0,0 +1,241 @@ +Grammatik + + 0 $accept: input $end + + 1 input: %empty + 2 | exp '\n' + + 3 exp: comp + 4 | exp '&' exp + 5 | exp '|' exp + 6 | exp '^' exp + 7 | '~' exp + 8 | '(' exp ')' + + 9 comp: CONSTANT + 10 | TOKEN + + +Terminale und die Regeln, in denen sie verwendet werden + +$end (0) 0 +'\n' (10) 2 +'&' (38) 4 +'(' (40) 8 +')' (41) 8 +'^' (94) 6 +'|' (124) 5 +'~' (126) 7 +error (256) +TOKEN (258) 10 +CONSTANT (259) 9 +NEG (260) + + +Nicht-Terminal und die Regeln, in denen sie verwendet werden + +$accept (13) + auf der linken Seite: 0 +input (14) + auf der linken Seite: 1 2, auf der rechten Seite: 0 +exp (15) + auf der linken Seite: 3 4 5 6 7 8, auf der rechten Seite: 2 4 5 + 6 7 8 +comp (16) + auf der linken Seite: 9 10, auf der rechten Seite: 3 + + +Zustand 0 + + 0 $accept: . input $end + + TOKEN schiebe und gehe zu Zustand 1 über + CONSTANT schiebe und gehe zu Zustand 2 über + '~' schiebe und gehe zu Zustand 3 über + '(' schiebe und gehe zu Zustand 4 über + + $default reduziere mit Regel 1 (input) + + input gehe zu Zustand 5 über + exp gehe zu Zustand 6 über + comp gehe zu Zustand 7 über + + +Zustand 1 + + 10 comp: TOKEN . + + $default reduziere mit Regel 10 (comp) + + +Zustand 2 + + 9 comp: CONSTANT . + + $default reduziere mit Regel 9 (comp) + + +Zustand 3 + + 7 exp: '~' . exp + + TOKEN schiebe und gehe zu Zustand 1 über + CONSTANT schiebe und gehe zu Zustand 2 über + '~' schiebe und gehe zu Zustand 3 über + '(' schiebe und gehe zu Zustand 4 über + + exp gehe zu Zustand 8 über + comp gehe zu Zustand 7 über + + +Zustand 4 + + 8 exp: '(' . exp ')' + + TOKEN schiebe und gehe zu Zustand 1 über + CONSTANT schiebe und gehe zu Zustand 2 über + '~' schiebe und gehe zu Zustand 3 über + '(' schiebe und gehe zu Zustand 4 über + + exp gehe zu Zustand 9 über + comp gehe zu Zustand 7 über + + +Zustand 5 + + 0 $accept: input . $end + + $end schiebe und gehe zu Zustand 10 über + + +Zustand 6 + + 2 input: exp . '\n' + 4 exp: exp . '&' exp + 5 | exp . '|' exp + 6 | exp . '^' exp + + '&' schiebe und gehe zu Zustand 11 über + '|' schiebe und gehe zu Zustand 12 über + '^' schiebe und gehe zu Zustand 13 über + '\n' schiebe und gehe zu Zustand 14 über + + +Zustand 7 + + 3 exp: comp . + + $default reduziere mit Regel 3 (exp) + + +Zustand 8 + + 4 exp: exp . '&' exp + 5 | exp . '|' exp + 6 | exp . '^' exp + 7 | '~' exp . + + $default reduziere mit Regel 7 (exp) + + +Zustand 9 + + 4 exp: exp . '&' exp + 5 | exp . '|' exp + 6 | exp . '^' exp + 8 | '(' exp . ')' + + '&' schiebe und gehe zu Zustand 11 über + '|' schiebe und gehe zu Zustand 12 über + '^' schiebe und gehe zu Zustand 13 über + ')' schiebe und gehe zu Zustand 15 über + + +Zustand 10 + + 0 $accept: input $end . + + $default annehmen + + +Zustand 11 + + 4 exp: exp '&' . exp + + TOKEN schiebe und gehe zu Zustand 1 über + CONSTANT schiebe und gehe zu Zustand 2 über + '~' schiebe und gehe zu Zustand 3 über + '(' schiebe und gehe zu Zustand 4 über + + exp gehe zu Zustand 16 über + comp gehe zu Zustand 7 über + + +Zustand 12 + + 5 exp: exp '|' . exp + + TOKEN schiebe und gehe zu Zustand 1 über + CONSTANT schiebe und gehe zu Zustand 2 über + '~' schiebe und gehe zu Zustand 3 über + '(' schiebe und gehe zu Zustand 4 über + + exp gehe zu Zustand 17 über + comp gehe zu Zustand 7 über + + +Zustand 13 + + 6 exp: exp '^' . exp + + TOKEN schiebe und gehe zu Zustand 1 über + CONSTANT schiebe und gehe zu Zustand 2 über + '~' schiebe und gehe zu Zustand 3 über + '(' schiebe und gehe zu Zustand 4 über + + exp gehe zu Zustand 18 über + comp gehe zu Zustand 7 über + + +Zustand 14 + + 2 input: exp '\n' . + + $default reduziere mit Regel 2 (input) + + +Zustand 15 + + 8 exp: '(' exp ')' . + + $default reduziere mit Regel 8 (exp) + + +Zustand 16 + + 4 exp: exp . '&' exp + 4 | exp '&' exp . + 5 | exp . '|' exp + 6 | exp . '^' exp + + $default reduziere mit Regel 4 (exp) + + +Zustand 17 + + 4 exp: exp . '&' exp + 5 | exp . '|' exp + 5 | exp '|' exp . + 6 | exp . '^' exp + + $default reduziere mit Regel 5 (exp) + + +Zustand 18 + + 4 exp: exp . '&' exp + 5 | exp . '|' exp + 6 | exp . '^' exp + 6 | exp '^' exp . + + $default reduziere mit Regel 6 (exp) diff --git a/lib/boolean/boolean.tab.c b/lib/boolean/boolean.tab.c new file mode 100644 index 000000000..0f221ac69 --- /dev/null +++ b/lib/boolean/boolean.tab.c @@ -0,0 +1,1539 @@ +/* A Bison parser, made by GNU Bison 3.0.4. */ + +/* Bison implementation for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + 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 + (at your option) 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 . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "3.0.4" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + +/* Substitute the type names. */ +#define YYSTYPE LOG_EXPRESSION_STYPE +/* Substitute the variable and function names. */ +#define yyparse log_expression_parse +#define yylex log_expression_lex +#define yyerror log_expression_error +#define yydebug log_expression_debug +#define yynerrs log_expression_nerrs + +#define yylval log_expression_lval +#define yychar log_expression_char + +/* Copy the first part of user declarations. */ +#line 1 "boolean.y" /* yacc.c:339 */ + +#include +#include +#include + +void log_expression_error(const char *s); +int log_expression_lex(); +int log_expression_parse(); +long lookup_token(char *token); + +#line 86 "boolean.tab.c" /* yacc.c:339 */ + +# ifndef YY_NULLPTR +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* In a future release of Bison, this section will be replaced + by #include "boolean.tab.h". */ +#ifndef YY_LOG_EXPRESSION_BOOLEAN_TAB_H_INCLUDED +# define YY_LOG_EXPRESSION_BOOLEAN_TAB_H_INCLUDED +/* Debug traces. */ +#ifndef LOG_EXPRESSION_DEBUG +# if defined YYDEBUG +#if YYDEBUG +# define LOG_EXPRESSION_DEBUG 1 +# else +# define LOG_EXPRESSION_DEBUG 0 +# endif +# else /* ! defined YYDEBUG */ +# define LOG_EXPRESSION_DEBUG 0 +# endif /* ! defined YYDEBUG */ +#endif /* ! defined LOG_EXPRESSION_DEBUG */ +#if LOG_EXPRESSION_DEBUG +extern int log_expression_debug; +#endif + +/* Token type. */ +#ifndef LOG_EXPRESSION_TOKENTYPE +# define LOG_EXPRESSION_TOKENTYPE + enum log_expression_tokentype + { + TOKEN = 258, + CONSTANT = 259, + NEG = 260 + }; +#endif + +/* Value type. */ +#if ! defined LOG_EXPRESSION_STYPE && ! defined LOG_EXPRESSION_STYPE_IS_DECLARED + +union LOG_EXPRESSION_STYPE +{ +#line 12 "boolean.y" /* yacc.c:355 */ + + char *token; + unsigned long constant; + +#line 145 "boolean.tab.c" /* yacc.c:355 */ +}; + +typedef union LOG_EXPRESSION_STYPE LOG_EXPRESSION_STYPE; +# define LOG_EXPRESSION_STYPE_IS_TRIVIAL 1 +# define LOG_EXPRESSION_STYPE_IS_DECLARED 1 +#endif + + +extern LOG_EXPRESSION_STYPE log_expression_lval; + +int log_expression_parse (void); + +#endif /* !YY_LOG_EXPRESSION_BOOLEAN_TAB_H_INCLUDED */ + +/* Copy the second part of user declarations. */ + +#line 162 "boolean.tab.c" /* yacc.c:358 */ + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#else +typedef signed char yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif +#endif + +#ifndef YY_ATTRIBUTE +# if (defined __GNUC__ \ + && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ + || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C +# define YY_ATTRIBUTE(Spec) __attribute__(Spec) +# else +# define YY_ATTRIBUTE(Spec) /* empty */ +# endif +#endif + +#ifndef YY_ATTRIBUTE_PURE +# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) +#endif + +#if !defined _Noreturn \ + && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) +# if defined _MSC_VER && 1200 <= _MSC_VER +# define _Noreturn __declspec (noreturn) +# else +# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(E) ((void) (E)) +#else +# define YYUSE(E) /* empty */ +#endif + +#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS +# include /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined LOG_EXPRESSION_STYPE_IS_TRIVIAL && LOG_EXPRESSION_STYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 10 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 21 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 13 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 4 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 11 +/* YYNSTATES -- Number of states. */ +#define YYNSTATES 19 + +/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned + by yylex, with out-of-bounds checking. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 260 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, without out-of-bounds checking. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, + 11, 12, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 7, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 6, 2, 10, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 8 +}; + +#if LOG_EXPRESSION_DEBUG + /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_uint8 yyrline[] = +{ + 0, 30, 30, 31, 35, 36, 37, 38, 39, 40, + 44, 45 +}; +#endif + +#if LOG_EXPRESSION_DEBUG || YYERROR_VERBOSE || 0 +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "TOKEN", "CONSTANT", "'&'", "'|'", "'^'", + "NEG", "'\\n'", "'~'", "'('", "')'", "$accept", "input", "exp", "comp", YY_NULLPTR +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[NUM] -- (External) token number corresponding to the + (internal) symbol number NUM (which must be that of a token). */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 38, 124, 94, 260, 10, + 126, 40, 41 +}; +# endif + +#define YYPACT_NINF -4 + +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-4))) + +#define YYTABLE_NINF -1 + +#define yytable_value_is_error(Yytable_value) \ + 0 + + /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int8 yypact[] = +{ + 1, -4, -4, 1, 1, 2, 12, -4, -4, 8, + -4, 1, 1, 1, -4, -4, -4, -4, -4 +}; + + /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 2, 11, 10, 0, 0, 0, 0, 4, 8, 0, + 1, 0, 0, 0, 3, 9, 5, 6, 7 +}; + + /* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -4, -4, -3, -4 +}; + + /* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = +{ + -1, 5, 6, 7 +}; + + /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_uint8 yytable[] = +{ + 8, 9, 10, 0, 1, 2, 0, 0, 16, 17, + 18, 3, 4, 11, 12, 13, 0, 11, 12, 13, + 15, 14 +}; + +static const yytype_int8 yycheck[] = +{ + 3, 4, 0, -1, 3, 4, -1, -1, 11, 12, + 13, 10, 11, 5, 6, 7, -1, 5, 6, 7, + 12, 9 +}; + + /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 3, 4, 10, 11, 14, 15, 16, 15, 15, + 0, 5, 6, 7, 9, 12, 15, 15, 15 +}; + + /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 13, 14, 14, 15, 15, 15, 15, 15, 15, + 16, 16 +}; + + /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 0, 2, 1, 3, 3, 3, 2, 3, + 1, 1 +}; + + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (0) + +/* Error token number */ +#define YYTERROR 1 +#define YYERRCODE 256 + + + +/* Enable debugging if requested. */ +#if LOG_EXPRESSION_DEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +/* This macro is provided for backward compatibility. */ +#ifndef YY_LOCATION_PRINT +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +#endif + + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + + +/*----------------------------------------. +| Print this symbol's value on YYOUTPUT. | +`----------------------------------------*/ + +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +{ + FILE *yyo = yyoutput; + YYUSE (yyo); + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + YYUSE (yytype); +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +{ + YYFPRINTF (yyoutput, "%s %s (", + yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +static void +yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule) +{ + unsigned long int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; + int yyi; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + yystos[yyssp[yyi + 1 - yynrhs]], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !LOG_EXPRESSION_DEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !LOG_EXPRESSION_DEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +yystrlen (const char *yystr) +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +yystpcpy (char *yydest, const char *yysrc) +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) +{ + YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = YY_NULLPTR; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; + + /* There are many possibilities here to consider: + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) + { + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } + } + } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; +} +#endif /* YYERROR_VERBOSE */ + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +{ + YYUSE (yyvaluep); + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; +/* Number of syntax errors so far. */ +int yynerrs; + + +/*----------. +| yyparse. | +`----------*/ + +int +yyparse (void) +{ + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + 'yyss': related to states. + 'yyvs': related to semantic values. + + Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = yylex (); + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + '$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 3: +#line 31 "boolean.y" /* yacc.c:1646 */ + { printf("\n\nresult = %#lx\n", (yyvsp[-1].constant)); } +#line 1239 "boolean.tab.c" /* yacc.c:1646 */ + break; + + case 5: +#line 36 "boolean.y" /* yacc.c:1646 */ + { (yyval.constant) = (yyvsp[-2].constant) & (yyvsp[0].constant); } +#line 1245 "boolean.tab.c" /* yacc.c:1646 */ + break; + + case 6: +#line 37 "boolean.y" /* yacc.c:1646 */ + { (yyval.constant) = (yyvsp[-2].constant) | (yyvsp[0].constant); } +#line 1251 "boolean.tab.c" /* yacc.c:1646 */ + break; + + case 7: +#line 38 "boolean.y" /* yacc.c:1646 */ + { (yyval.constant) = (yyvsp[-2].constant) ^ (yyvsp[0].constant); } +#line 1257 "boolean.tab.c" /* yacc.c:1646 */ + break; + + case 8: +#line 39 "boolean.y" /* yacc.c:1646 */ + { (yyval.constant) = ~(yyvsp[0].constant); printf("neg\n"); } +#line 1263 "boolean.tab.c" /* yacc.c:1646 */ + break; + + case 9: +#line 40 "boolean.y" /* yacc.c:1646 */ + { (yyval.constant) = (yyvsp[-1].constant); printf("subex"); } +#line 1269 "boolean.tab.c" /* yacc.c:1646 */ + break; + + case 10: +#line 44 "boolean.y" /* yacc.c:1646 */ + { (yyval.constant) = (yyvsp[0].constant); printf("const %ld", (yyvsp[0].constant)); } +#line 1275 "boolean.tab.c" /* yacc.c:1646 */ + break; + + case 11: +#line 45 "boolean.y" /* yacc.c:1646 */ + { (yyval.constant) = lookup_token((yyvsp[0].token)); printf("token '%s'", (yyvsp[0].token)); } +#line 1281 "boolean.tab.c" /* yacc.c:1646 */ + break; + + +#line 1285 "boolean.tab.c" /* yacc.c:1646 */ + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + /* Now 'shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) + { + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; + } +# undef YYSYNTAX_ERROR +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined yyoverflow || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + } + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + return yyresult; +} +#line 48 "boolean.y" /* yacc.c:1906 */ + + +long lookup_token(char *token) +{ + if (!strcmp(token, "a")) + return 201; + else if (!strcmp(token, "b")) + return 202; + if (!strcmp(token, "c")) + return 203; + if (!strcmp(token, "d")) + return 204; + else + return 1111; + +} + +int main(int argc, char *argv[]) { + do { + log_expression_parse(); + } while (!feof(stdin)); +} + +void log_expression_error(const char *s) { + printf("EEK, parse error! Message: %s", s); + exit(-1); +} diff --git a/lib/boolean/boolean.tab.h b/lib/boolean/boolean.tab.h new file mode 100644 index 000000000..b2d6acc4f --- /dev/null +++ b/lib/boolean/boolean.tab.h @@ -0,0 +1,85 @@ +/* A Bison parser, made by GNU Bison 3.0.4. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + 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 + (at your option) 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 . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +#ifndef YY_LOG_EXPRESSION_BOOLEAN_TAB_H_INCLUDED +# define YY_LOG_EXPRESSION_BOOLEAN_TAB_H_INCLUDED +/* Debug traces. */ +#ifndef LOG_EXPRESSION_DEBUG +# if defined YYDEBUG +#if YYDEBUG +# define LOG_EXPRESSION_DEBUG 1 +# else +# define LOG_EXPRESSION_DEBUG 0 +# endif +# else /* ! defined YYDEBUG */ +# define LOG_EXPRESSION_DEBUG 0 +# endif /* ! defined YYDEBUG */ +#endif /* ! defined LOG_EXPRESSION_DEBUG */ +#if LOG_EXPRESSION_DEBUG +extern int log_expression_debug; +#endif + +/* Token type. */ +#ifndef LOG_EXPRESSION_TOKENTYPE +# define LOG_EXPRESSION_TOKENTYPE + enum log_expression_tokentype + { + TOKEN = 258, + CONSTANT = 259, + NEG = 260 + }; +#endif + +/* Value type. */ +#if ! defined LOG_EXPRESSION_STYPE && ! defined LOG_EXPRESSION_STYPE_IS_DECLARED + +union LOG_EXPRESSION_STYPE +{ +#line 12 "boolean.y" /* yacc.c:1909 */ + + char *token; + unsigned long constant; + +#line 73 "boolean.tab.h" /* yacc.c:1909 */ +}; + +typedef union LOG_EXPRESSION_STYPE LOG_EXPRESSION_STYPE; +# define LOG_EXPRESSION_STYPE_IS_TRIVIAL 1 +# define LOG_EXPRESSION_STYPE_IS_DECLARED 1 +#endif + + +extern LOG_EXPRESSION_STYPE log_expression_lval; + +int log_expression_parse (void); + +#endif /* !YY_LOG_EXPRESSION_BOOLEAN_TAB_H_INCLUDED */ diff --git a/lib/boolean/boolean.y b/lib/boolean/boolean.y new file mode 100644 index 000000000..3573d3cba --- /dev/null +++ b/lib/boolean/boolean.y @@ -0,0 +1,74 @@ +%{ +#include +#include +#include + +void log_expression_error(const char *s); +int log_expression_lex(); +int log_expression_parse(); +long lookup_token(char *token); +%} + +%union { + char *token; + unsigned long constant; +} + +%token TOKEN +%token CONSTANT + +%type exp comp + + +%left '&' '|' '^' +%precedence NEG + +%define api.prefix {log_expression_} + +%% + +input: + | exp '\n' { printf("\n\nresult = %#lx\n", $1); } +; + +exp : + comp + | exp '&' exp { $$ = $1 & $3; } + | exp '|' exp { $$ = $1 | $3; } + | exp '^' exp { $$ = $1 ^ $3; } + | '~' exp %prec NEG { $$ = ~$2; printf("neg\n"); } + | '(' exp ')' { $$ = $2; printf("subex"); } +; + +comp : + CONSTANT { $$ = $1; printf("const %ld", $1); } + | TOKEN { $$ = lookup_token($1); printf("token '%s'", $1); } +; + +%% + +long lookup_token(char *token) +{ + if (!strcmp(token, "a")) + return 201; + else if (!strcmp(token, "b")) + return 202; + if (!strcmp(token, "c")) + return 203; + if (!strcmp(token, "d")) + return 204; + else + return 1111; + +} + +int main(int argc, char *argv[]) { + do { + log_expression_parse(); + } while (!feof(stdin)); +} + +void log_expression_error(const char *s) { + printf("EEK, parse error! Message: %s", s); + exit(-1); +} \ No newline at end of file diff --git a/lib/boolean/lex.log_expression_.c b/lib/boolean/lex.log_expression_.c new file mode 100644 index 000000000..6c3def162 --- /dev/null +++ b/lib/boolean/lex.log_expression_.c @@ -0,0 +1,1804 @@ + +#line 3 "lex.log_expression_.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define yy_create_buffer log_expression__create_buffer +#define yy_delete_buffer log_expression__delete_buffer +#define yy_flex_debug log_expression__flex_debug +#define yy_init_buffer log_expression__init_buffer +#define yy_flush_buffer log_expression__flush_buffer +#define yy_load_buffer_state log_expression__load_buffer_state +#define yy_switch_to_buffer log_expression__switch_to_buffer +#define yyin log_expression_in +#define yyleng log_expression_leng +#define yylex log_expression_lex +#define yylineno log_expression_lineno +#define yyout log_expression_out +#define yyrestart log_expression_restart +#define yytext log_expression_text +#define yywrap log_expression_wrap +#define yyalloc log_expression_alloc +#define yyrealloc log_expression_realloc +#define yyfree log_expression_free + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 0 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE log_expression_restart(log_expression_in ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +extern yy_size_t log_expression_leng; + +extern FILE *log_expression_in, *log_expression_out; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + #define YY_LINENO_REWIND_TO(ptr) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up log_expression_text. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up log_expression_text again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + yy_size_t yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via log_expression_restart()), so that the user can continue scanning by + * just pointing log_expression_in at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when log_expression_text is formed. */ +static char yy_hold_char; +static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */ +yy_size_t log_expression_leng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow log_expression_wrap()'s to do buffer switches + * instead of setting up a fresh log_expression_in. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void log_expression_restart (FILE *input_file ); +void log_expression__switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE log_expression__create_buffer (FILE *file,int size ); +void log_expression__delete_buffer (YY_BUFFER_STATE b ); +void log_expression__flush_buffer (YY_BUFFER_STATE b ); +void log_expression_push_buffer_state (YY_BUFFER_STATE new_buffer ); +void log_expression_pop_buffer_state (void ); + +static void log_expression_ensure_buffer_stack (void ); +static void log_expression__load_buffer_state (void ); +static void log_expression__init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER log_expression__flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE log_expression__scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE log_expression__scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE log_expression__scan_bytes (yyconst char *bytes,yy_size_t len ); + +void *log_expression_alloc (yy_size_t ); +void *log_expression_realloc (void *,yy_size_t ); +void log_expression_free (void * ); + +#define yy_new_buffer log_expression__create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + log_expression_ensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + log_expression__create_buffer(log_expression_in,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + log_expression_ensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + log_expression__create_buffer(log_expression_in,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define log_expression_wrap() (/*CONSTCOND*/1) +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +FILE *log_expression_in = (FILE *) 0, *log_expression_out = (FILE *) 0; + +typedef int yy_state_type; + +extern int log_expression_lineno; + +int log_expression_lineno = 1; + +extern char *log_expression_text; +#ifdef yytext_ptr +#undef yytext_ptr +#endif +#define yytext_ptr log_expression_text + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +#if defined(__GNUC__) && __GNUC__ >= 3 +__attribute__((__noreturn__)) +#endif +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up log_expression_text. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + log_expression_leng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 5 +#define YY_END_OF_BUFFER 6 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[12] = + { 0, + 0, 0, 6, 5, 1, 2, 4, 3, 4, 3, + 0 + } ; + +static yyconst YY_CHAR yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 5, 5, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst YY_CHAR yy_meta[6] = + { 0, + 1, 1, 1, 2, 3 + } ; + +static yyconst flex_uint16_t yy_base[14] = + { 0, + 0, 0, 8, 9, 9, 9, 0, 0, 0, 0, + 9, 5, 3 + } ; + +static yyconst flex_int16_t yy_def[14] = + { 0, + 11, 1, 11, 11, 11, 11, 12, 13, 12, 13, + 0, 11, 11 + } ; + +static yyconst flex_uint16_t yy_nxt[15] = + { 0, + 4, 5, 6, 7, 8, 10, 9, 11, 3, 11, + 11, 11, 11, 11 + } ; + +static yyconst flex_int16_t yy_chk[15] = + { 0, + 1, 1, 1, 1, 1, 13, 12, 3, 11, 11, + 11, 11, 11, 11 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int log_expression__flex_debug; +int log_expression__flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *log_expression_text; +#line 1 "boolean.l" +#line 2 "boolean.l" +#include +#include + +#include "boolean.tab.h" // to get the token types that we return + +#line 498 "lex.log_expression_.c" + +#define INITIAL 0 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int log_expression_lex_destroy (void ); + +int log_expression_get_debug (void ); + +void log_expression_set_debug (int debug_flag ); + +YY_EXTRA_TYPE log_expression_get_extra (void ); + +void log_expression_set_extra (YY_EXTRA_TYPE user_defined ); + +FILE *log_expression_get_in (void ); + +void log_expression_set_in (FILE * _in_str ); + +FILE *log_expression_get_out (void ); + +void log_expression_set_out (FILE * _out_str ); + +yy_size_t log_expression_get_leng (void ); + +char *log_expression_get_text (void ); + +int log_expression_get_lineno (void ); + +void log_expression_set_lineno (int _line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int log_expression_wrap (void ); +#else +extern int log_expression_wrap (void ); +#endif +#endif + +#ifndef YY_NO_UNPUT + + static void yyunput (int c,char *buf_ptr ); + +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( log_expression_text, log_expression_leng, 1, log_expression_out )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( log_expression_in )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( log_expression_in ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, log_expression_in))==0 && ferror(log_expression_in)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(log_expression_in); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int log_expression_lex (void); + +#define YY_DECL int log_expression_lex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after log_expression_text and log_expression_leng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK /*LINTED*/break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! log_expression_in ) + log_expression_in = stdin; + + if ( ! log_expression_out ) + log_expression_out = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + log_expression_ensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + log_expression__create_buffer(log_expression_in,YY_BUF_SIZE ); + } + + log_expression__load_buffer_state( ); + } + + { +#line 12 "boolean.l" + + +#line 719 "lex.log_expression_.c" + + while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of log_expression_text. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + do + { + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 12 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 9 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +/* rule 1 can match eol */ +YY_RULE_SETUP +#line 14 "boolean.l" +; // ignore whitespace + YY_BREAK +case 2: +YY_RULE_SETUP +#line 15 "boolean.l" +; //operators + YY_BREAK +case 3: +YY_RULE_SETUP +#line 16 "boolean.l" +{ log_expression_lval.token = strdup(log_expression_text); return TOKEN; } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 17 "boolean.l" +{ log_expression_lval.constant = atoi(log_expression_text); return CONSTANT; } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 19 "boolean.l" +ECHO; + YY_BREAK +#line 802 "lex.log_expression_.c" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed log_expression_in at a new source and called + * log_expression_lex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = log_expression_in; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( log_expression_wrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * log_expression_text, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of user's declarations */ +} /* end of log_expression_lex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = (yytext_ptr); + yy_size_t number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (yy_size_t) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + yy_size_t num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + yy_size_t new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + log_expression_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + log_expression_restart(log_expression_in ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) log_expression_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + yy_state_type yy_current_state; + char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 12 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + int yy_is_jam; + char *yy_cp = (yy_c_buf_p); + + YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 12 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 11); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_UNPUT + + static void yyunput (int c, char * yy_bp ) +{ + char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up log_expression_text */ + *yy_cp = (yy_hold_char); + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + yy_size_t number_to_move = (yy_n_chars) + 2; + char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} + +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + yy_size_t offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + log_expression_restart(log_expression_in ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( log_expression_wrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve log_expression_text */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void log_expression_restart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + log_expression_ensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + log_expression__create_buffer(log_expression_in,YY_BUF_SIZE ); + } + + log_expression__init_buffer(YY_CURRENT_BUFFER,input_file ); + log_expression__load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void log_expression__switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * log_expression_pop_buffer_state(); + * log_expression_push_buffer_state(new_buffer); + */ + log_expression_ensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + log_expression__load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (log_expression_wrap()) processing, but the only time this flag + * is looked at is after log_expression_wrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void log_expression__load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + log_expression_in = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE log_expression__create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) log_expression_alloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in log_expression__create_buffer()" ); + + b->yy_buf_size = (yy_size_t)size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) log_expression_alloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in log_expression__create_buffer()" ); + + b->yy_is_our_buffer = 1; + + log_expression__init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with log_expression__create_buffer() + * + */ + void log_expression__delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + log_expression_free((void *) b->yy_ch_buf ); + + log_expression_free((void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a log_expression_restart() or at EOF. + */ + static void log_expression__init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + log_expression__flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then log_expression__init_buffer was _probably_ + * called from log_expression_restart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void log_expression__flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + log_expression__load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void log_expression_push_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + log_expression_ensure_buffer_stack(); + + /* This block is copied from log_expression__switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from log_expression__switch_to_buffer. */ + log_expression__load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void log_expression_pop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + log_expression__delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + log_expression__load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void log_expression_ensure_buffer_stack (void) +{ + yy_size_t num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; // After all that talk, this was set to 1 anyways... + (yy_buffer_stack) = (struct yy_buffer_state**)log_expression_alloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in log_expression_ensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + yy_size_t grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)log_expression_realloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in log_expression_ensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE log_expression__scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) log_expression_alloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in log_expression__scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + log_expression__switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to log_expression_lex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * log_expression__scan_bytes() instead. + */ +YY_BUFFER_STATE log_expression__scan_string (yyconst char * yystr ) +{ + + return log_expression__scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to log_expression_lex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE log_expression__scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + yy_size_t i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) log_expression_alloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in log_expression__scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = log_expression__scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in log_expression__scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up log_expression_text. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + log_expression_text[log_expression_leng] = (yy_hold_char); \ + (yy_c_buf_p) = log_expression_text + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + log_expression_leng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int log_expression_get_lineno (void) +{ + + return log_expression_lineno; +} + +/** Get the input stream. + * + */ +FILE *log_expression_get_in (void) +{ + return log_expression_in; +} + +/** Get the output stream. + * + */ +FILE *log_expression_get_out (void) +{ + return log_expression_out; +} + +/** Get the length of the current token. + * + */ +yy_size_t log_expression_get_leng (void) +{ + return log_expression_leng; +} + +/** Get the current token. + * + */ + +char *log_expression_get_text (void) +{ + return log_expression_text; +} + +/** Set the current line number. + * @param _line_number line number + * + */ +void log_expression_set_lineno (int _line_number ) +{ + + log_expression_lineno = _line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param _in_str A readable stream. + * + * @see log_expression__switch_to_buffer + */ +void log_expression_set_in (FILE * _in_str ) +{ + log_expression_in = _in_str ; +} + +void log_expression_set_out (FILE * _out_str ) +{ + log_expression_out = _out_str ; +} + +int log_expression_get_debug (void) +{ + return log_expression__flex_debug; +} + +void log_expression_set_debug (int _bdebug ) +{ + log_expression__flex_debug = _bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from log_expression_lex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + log_expression_in = stdin; + log_expression_out = stdout; +#else + log_expression_in = (FILE *) 0; + log_expression_out = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * log_expression_lex_init() + */ + return 0; +} + +/* log_expression_lex_destroy is for both reentrant and non-reentrant scanners. */ +int log_expression_lex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + log_expression__delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + log_expression_pop_buffer_state(); + } + + /* Destroy the stack itself. */ + log_expression_free((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * log_expression_lex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + + int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *log_expression_alloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *log_expression_realloc (void * ptr, yy_size_t size ) +{ + + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void log_expression_free (void * ptr ) +{ + free( (char *) ptr ); /* see log_expression_realloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 19 "boolean.l" + + diff --git a/lib/cfg.c b/lib/cfg.c deleted file mode 100644 index 336b6dcd5..000000000 --- a/lib/cfg.c +++ /dev/null @@ -1,366 +0,0 @@ -/** Configuration parser. - * - * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC - *********************************************************************************/ - -#include -#include -#include -#include -#include - -#include "utils.h" -#include "list.h" -#include "cfg.h" -#include "node.h" -#include "path.h" -#include "hooks.h" - -void cfg_init(config_t *cfg) -{ - config_init(cfg); -} - -void cfg_destroy(config_t *cfg) -{ - config_destroy(cfg); -} - -int cfg_parse(const char *filename, config_t *cfg, struct settings *set, - struct list *nodes, struct list *paths) -{ - int ret = CONFIG_FALSE; - char *filename_cpy, *include_dir; - - config_init(cfg); - - filename_cpy = strdup(filename); - include_dir = dirname(filename_cpy); - - /* Setup libconfig */ - config_set_auto_convert(cfg, 1); - config_set_include_dir(cfg, include_dir); - - free(filename_cpy); - - if (strcmp("-", filename) == 0) - ret = config_read(cfg, stdin); - else if (access(filename, F_OK) != -1) - ret = config_read_file(cfg, filename); - else - error("Invalid configuration file name: %s", filename); - - if (ret != CONFIG_TRUE) { - error("Failed to parse configuration: %s in %s:%d", - config_error_text(cfg), - config_error_file(cfg) ? config_error_file(cfg) : filename, - config_error_line(cfg) - ); - } - - config_setting_t *cfg_root = config_root_setting(cfg); - - /* Parse global settings */ - if (set) { - if (!cfg_root || !config_setting_is_group(cfg_root)) - error("Missing global section in config file: %s", filename); - - cfg_parse_global(cfg_root, set); - } - - /* Parse nodes */ - if (nodes) { - config_setting_t *cfg_nodes = config_setting_get_member(cfg_root, "nodes"); - if (!cfg_nodes || !config_setting_is_group(cfg_nodes)) - error("Missing node section in config file: %s", filename); - - for (int i = 0; i < config_setting_length(cfg_nodes); i++) { - config_setting_t *cfg_node = config_setting_get_elem(cfg_nodes, i); - cfg_parse_node(cfg_node, nodes, set); - } - } - - /* Parse paths */ - if (paths) { - config_setting_t *cfg_paths = config_setting_get_member(cfg_root, "paths"); - if (!cfg_paths || !config_setting_is_list(cfg_paths)) - error("Missing path section in config file: %s", filename); - - for (int i = 0; i < config_setting_length(cfg_paths); i++) { - config_setting_t *cfg_path = config_setting_get_elem(cfg_paths, i); - cfg_parse_path(cfg_path, paths, nodes, set); - } - } - - return 0; -} - -int cfg_parse_plugins(config_setting_t *cfg) -{ - if (!config_setting_is_array(cfg)) - cerror(cfg, "Setting 'plugins' must be a list of strings"); - - for (int i = 0; i < config_setting_length(cfg); i++) { - void *handle; - const char *path; - - path = config_setting_get_string_elem(cfg, i); - if (!path) - cerror(cfg, "Setting 'plugins' must be a list of strings"); - - handle = dlopen(path, RTLD_NOW); - if (!handle) - error("Failed to load plugin %s", dlerror()); - } - - return 0; -} - -int cfg_parse_global(config_setting_t *cfg, struct settings *set) -{ - config_setting_t *cfg_plugins; - - if (!config_setting_lookup_int(cfg, "affinity", &set->affinity)) - set->affinity = 0; - - if (!config_setting_lookup_int(cfg, "priority", &set->priority)) - set->priority = 0; - - if (!config_setting_lookup_int(cfg, "debug", &set->debug)) - set->debug = V; - - if (!config_setting_lookup_float(cfg, "stats", &set->stats)) - set->stats = 0; - - cfg_plugins = config_setting_get_member(cfg, "plugins"); - if (cfg_plugins) - cfg_parse_plugins(cfg_plugins); - - log_setlevel(set->debug, -1); - - return 0; -} - -int cfg_parse_path(config_setting_t *cfg, - struct list *paths, struct list *nodes, struct settings *set) -{ - config_setting_t *cfg_out, *cfg_hook; - const char *in; - int ret, reverse; - struct path *p; - - /* Allocate memory and intialize path structure */ - p = alloc(sizeof(struct path)); - path_init(p); - - /* Input node */ - if (!config_setting_lookup_string(cfg, "in", &in) && - !config_setting_lookup_string(cfg, "from", &in) && - !config_setting_lookup_string(cfg, "src", &in) && - !config_setting_lookup_string(cfg, "source", &in)) - cerror(cfg, "Missing input node for path"); - - p->in = list_lookup(nodes, in); - if (!p->in) - cerror(cfg, "Invalid input node '%s'", in); - - /* Output node(s) */ - if (!(cfg_out = config_setting_get_member(cfg, "out")) && - !(cfg_out = config_setting_get_member(cfg, "to")) && - !(cfg_out = config_setting_get_member(cfg, "dst")) && - !(cfg_out = config_setting_get_member(cfg, "dest")) && - !(cfg_out = config_setting_get_member(cfg, "sink"))) - cerror(cfg, "Missing output nodes for path"); - - ret = cfg_parse_nodelist(cfg_out, &p->destinations, nodes); - if (ret <= 0) - cerror(cfg_out, "Invalid output nodes"); - - /* Check if nodes are suitable */ - if (p->in->_vt->read == NULL) - cerror(cfg, "Input node '%s' is not supported as a source.", node_name(p->in)); - - list_foreach(struct node *n, &p->destinations) { - if (n->_vt->write == NULL) - cerror(cfg_out, "Output node '%s' is not supported as a destination.", node_name(n)); - } - - /* Optional settings */ - cfg_hook = config_setting_get_member(cfg, "hook"); - if (cfg_hook) - cfg_parse_hooklist(cfg_hook, &p->hooks); - - if (!config_setting_lookup_int(cfg, "values", &p->samplelen)) - p->samplelen = DEFAULT_VALUES; - if (!config_setting_lookup_int(cfg, "queuelen", &p->queuelen)) - p->queuelen = DEFAULT_QUEUELEN; - if (!config_setting_lookup_bool(cfg, "reverse", &reverse)) - reverse = 0; - if (!config_setting_lookup_bool(cfg, "enabled", &p->enabled)) - p->enabled = 1; - if (!config_setting_lookup_float(cfg, "rate", &p->rate)) - p->rate = 0; /* disabled */ - - if (!IS_POW2(p->queuelen)) { - p->queuelen = LOG2_CEIL(p->queuelen); - warn("Queue length should always be a power of 2. Adjusting to %d", p->queuelen); - } - - p->cfg = cfg; - - list_push(paths, p); - - if (reverse) { - if (list_length(&p->destinations) > 1) - cerror(cfg, "Can't reverse path with multiple destination nodes"); - - struct path *r = memdup(p, sizeof(struct path)); - path_init(r); - - /* Swap source and destination node */ - r->in = list_first(&p->destinations); - list_push(&r->destinations, p->in); - - if (cfg_hook) - cfg_parse_hooklist(cfg_hook, &r->hooks); - - list_push(paths, r); - } - - return 0; -} - -int cfg_parse_nodelist(config_setting_t *cfg, struct list *list, struct list *all) { - const char *str; - struct node *node; - - switch (config_setting_type(cfg)) { - case CONFIG_TYPE_STRING: - str = config_setting_get_string(cfg); - if (str) { - node = list_lookup(all, str); - if (node) - list_push(list, node); - else - cerror(cfg, "Unknown outgoing node '%s'", str); - } - else - cerror(cfg, "Invalid outgoing node"); - break; - - case CONFIG_TYPE_ARRAY: - for (int i = 0; i < config_setting_length(cfg); i++) { - config_setting_t *elm = config_setting_get_elem(cfg, i); - - str = config_setting_get_string(elm); - if (str) { - node = list_lookup(all, str); - if (!node) - cerror(elm, "Unknown outgoing node '%s'", str); - else if (node->_vt->write == NULL) - cerror(cfg, "Output node '%s' is not supported as a sink.", node_name(node)); - - list_push(list, node); - } - else - cerror(cfg, "Invalid outgoing node"); - } - break; - - default: - cerror(cfg, "Invalid output node(s)"); - } - - return list_length(list); -} - -int cfg_parse_node(config_setting_t *cfg, struct list *nodes, struct settings *set) -{ - const char *type, *name; - int ret; - - struct node *n; - struct node_type *vt; - - /* Required settings */ - if (!config_setting_lookup_string(cfg, "type", &type)) - cerror(cfg, "Missing node type"); - - name = config_setting_name(cfg); - - vt = list_lookup(&node_types, type); - if (!vt) - cerror(cfg, "Invalid type for node '%s'", config_setting_name(cfg)); - - n = node_create(vt); - - n->name = name; - n->cfg = cfg; - - ret = node_parse(n, cfg); - if (ret) - cerror(cfg, "Failed to parse node '%s'", node_name(n)); - - if (config_setting_lookup_int(cfg, "vectorize", &n->vectorize)) { - config_setting_t *cfg_vectorize = config_setting_lookup(cfg, "vectorize"); - - if (n->vectorize <= 0) - cerror(cfg_vectorize, "Invalid value for `vectorize` %d. Must be natural number!", n->vectorize); - if (vt->vectorize && vt->vectorize < n->vectorize) - cerror(cfg_vectorize, "Invalid value for `vectorize`. Node type %s requires a number smaller than %d!", - node_name_type(n), vt->vectorize); - } - else - n->vectorize = 1; - - if (!config_setting_lookup_int(cfg, "affinity", &n->affinity)) - n->affinity = set->affinity; - - list_push(nodes, n); - - return ret; -} - -int cfg_parse_hooklist(config_setting_t *cfg, struct list *list) { - switch (config_setting_type(cfg)) { - case CONFIG_TYPE_STRING: - cfg_parse_hook(cfg, list); - break; - - case CONFIG_TYPE_ARRAY: - for (int i = 0; i < config_setting_length(cfg); i++) - cfg_parse_hook(config_setting_get_elem(cfg, i), list); - break; - - default: - cerror(cfg, "Invalid hook functions"); - } - - return list_length(list); -} - -int cfg_parse_hook(config_setting_t *cfg, struct list *list) -{ - struct hook *hook, *copy; - char *name, *param; - const char *hookline = config_setting_get_string(cfg); - if (!hookline) - cerror(cfg, "Invalid hook function"); - - name = strtok((char *) hookline, ":"); - param = strtok(NULL, ""); - - debug(3, "Hook: %s => %s", name, param); - - hook = list_lookup(&hooks, name); - if (!hook) - cerror(cfg, "Unknown hook function '%s'", name); - - copy = memdup(hook, sizeof(struct hook)); - copy->parameter = param; - - list_push(list, copy); - - return 0; -} diff --git a/lib/fpga/Makefile.inc b/lib/fpga/Makefile.inc new file mode 100644 index 000000000..0e7058429 --- /dev/null +++ b/lib/fpga/Makefile.inc @@ -0,0 +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) +endif +endif + +-include lib/fpga/ips/Makefile.inc \ No newline at end of file diff --git a/lib/fpga/card.c b/lib/fpga/card.c new file mode 100644 index 000000000..a8b90cc7b --- /dev/null +++ b/lib/fpga/card.c @@ -0,0 +1,286 @@ +/** FPGA card. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#include + +#include "config.h" +#include "log.h" +#include "list.h" +#include "utils.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) +{ + assert(c->state = STATE_DESTROYED); + + c->vfio_container = vc; + c->pci = pci; + + list_init(&c->ips); + + /* Default values */ + c->filter.id.vendor = FPGA_PCI_VID_XILINX; + c->filter.id.device = FPGA_PCI_PID_VFPGA; + + c->affinity = 0; + c->do_reset = 0; + + c->state = STATE_INITIALIZED; + + 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; + + c->name = config_setting_name(cfg); + + config_setting_lookup_int(cfg, "affinity", &c->affinity); + config_setting_lookup_bool(cfg, "do_reset", &c->do_reset); + + cfg_slot = config_setting_get_member(cfg, "slot"); + if (cfg_slot) { + slot = config_setting_get_string(cfg_slot); + if (slot) { + ret = pci_device_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_device_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); + + const char *vlnv; + + struct fpga_ip_type *vt; + struct fpga_ip ip = { + .card = c, + .state = STATE_DESTROYED + }; + + if (!config_setting_lookup_string(cfg, "vlnv", &vlnv)) + cerror(cfg, "FPGA IP core %s is missing the VLNV identifier", c->name); + + vt = fpga_ip_type_lookup(vlnv); + if (!vt) + cerror(cfg, "FPGA IP core VLNV identifier '%s' is invalid", vlnv); + + ret = fpga_ip_init(&ip, vt); + if (ret) + error("Failed to initalize FPGA IP core"); + + ret = fpga_ip_parse(&ip, cfg_ip); + if (ret) + cerror(cfg_ip, "Failed to parse FPGA IP core"); + + list_push(&c->ips, memdup(&ip, sizeof(ip))); + } + + c->cfg = cfg; + c->state = STATE_PARSED; + + return 0; +} + +int fpga_card_parse_list(struct list *cards, config_setting_t *cfg) +{ + int ret; + + if (!config_setting_is_group(cfg)) + cerror(cfg, "FPGA configuration section must be a group"); + + for (int i = 0; i < config_setting_length(cfg); i++) { + config_setting_t *cfg_fpga = config_setting_get_elem(cfg, i); + + struct fpga_card c; + + ret = fpga_card_parse(&c, cfg_fpga); + if (ret) + cerror(cfg_fpga, "Failed to parse FPGA card configuration"); + + list_push(cards, memdup(&c, sizeof(c))); + } + + return 0; +} + +int fpga_card_start(struct fpga_card *c) +{ + int ret; + + struct pci_device *pdev; + + assert(c->state == STATE_CHECKED); + + /* Search for FPGA card */ + pdev = pci_lookup_device(c->pci, &c->filter); + if (!pdev) + error("Failed to find PCI device"); + + /* Attach PCIe card to VFIO container */ + ret = vfio_pci_attach(&c->vfio_device, c->vfio_container, pdev); + if (ret) + error("Failed to attach VFIO device"); + + /* Map PCIe BAR */ + c->map = vfio_map_region(&c->vfio_device, 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->vfio_device); + if (ret) + serror("Failed to enable PCI device"); + + /* Reset system? */ + if (c->do_reset) { + /* Reset / detect PCI device */ + ret = vfio_pci_reset(&c->vfio_device); + if (ret) + serror("Failed to reset PCI device"); + + ret = fpga_card_reset(c); + if (ret) + error("Failed to reset FGPA card"); + } + + /* Initialize IP cores */ + for (size_t j = 0; j < list_length(&c->ips); j++) { + struct fpga_ip *i = list_at(&c->ips, j); + + ret = fpga_ip_start(i); + if (ret) + error("Failed to initalize FPGA IP core: %s (%u)", i->name, ret); + } + + c->state = STATE_STARTED; + + return 0; +} + +int fpga_card_stop(struct fpga_card *c) +{ + int ret; + + assert(c->state == STATE_STOPPED); + + for (size_t j = 0; j < list_length(&c->ips); j++) { + struct fpga_ip *i = list_at(&c->ips, j); + + ret = fpga_ip_stop(i); + if (ret) + error("Failed to stop FPGA IP core: %s (%u)", i->name, ret); + } + + c->state = STATE_STOPPED; + + return 0; +} + +void fpga_card_dump(struct fpga_card *c) +{ + info("VILLASfpga card:"); + { INDENT + info("Slot: %04x:%02x:%02x.%d", c->vfio_device.pci_device->slot.domain, c->vfio_device.pci_device->slot.bus, c->vfio_device.pci_device->slot.device, c->vfio_device.pci_device->slot.function); + info("Vendor ID: %04x", c->vfio_device.pci_device->id.vendor); + info("Device ID: %04x", c->vfio_device.pci_device->id.device); + info("Class ID: %04x", c->vfio_device.pci_device->id.class); + + info("BAR0 mapped at %p", c->map); + + info("IP blocks:"); + for (size_t j = 0; j < list_length(&c->ips); j++) { INDENT + struct fpga_ip *i = list_at(&c->ips, j); + + fpga_ip_dump(i); + } + } + + vfio_dump(c->vfio_device.group->container); +} + +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->vfio_device.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->vfio_device.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 = STATE_INITIALIZED; + + return 0; +} \ No newline at end of file diff --git a/lib/fpga/fifo.c b/lib/fpga/fifo.c deleted file mode 100644 index fc8beaf19..000000000 --- a/lib/fpga/fifo.c +++ /dev/null @@ -1,104 +0,0 @@ -/** FIFO related helper functions - * - * These functions present a simpler interface to Xilinx' FIFO driver (XLlFifo_*) - * - * @author Steffen Vogel - * @copyright 2016, Steffen Vogel - **********************************************************************************/ - -#include - -#include - -#include "utils.h" -#include "fpga/ip.h" -#include "fpga/fifo.h" -#include "fpga/intc.h" - -int fifo_init(struct ip *c) -{ - struct fifo *fifo = &c->fifo; - XLlFifo *xfifo = &fifo->inst; - - int ret; - - XLlFifo_Config fifo_cfg = { - .BaseAddress = (uintptr_t) c->card->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 */ - }; - - ret = XLlFifo_CfgInitialize(xfifo, &fifo_cfg, (uintptr_t) c->card->map + c->baseaddr); - if (ret != XST_SUCCESS) - return -1; - - XLlFifo_IntEnable(xfifo, XLLF_INT_RC_MASK); /* Receive complete IRQ */ - - return 0; -} - -ssize_t fifo_write(struct ip *c, char *buf, size_t len) -{ - XLlFifo *fifo = &c->fifo.inst; - uint32_t tdfv; - - tdfv = XLlFifo_TxVacancy(fifo); - if (tdfv < len) - return -1; - - XLlFifo_Write(fifo, buf, len); - XLlFifo_TxSetLen(fifo, len); - - return len; -} - -ssize_t fifo_read(struct ip *c, char *buf, size_t len) -{ - XLlFifo *fifo = &c->fifo.inst; - - size_t nextlen = 0; - uint32_t rxlen; - - while (!XLlFifo_IsRxDone(fifo)) - intc_wait(c->card->intc, c->irq); - XLlFifo_IntClear(fifo, XLLF_INT_RC_MASK); - - /* Get length of next frame */ - rxlen = XLlFifo_RxGetLen(fifo); - nextlen = MIN(rxlen, len); - - /* Read from FIFO */ - XLlFifo_Read(fifo, buf, nextlen); - - return nextlen; -} - -int fifo_parse(struct ip *c) -{ - struct fifo *fifo = &c->fifo; - - int baseaddr_axi4; - - if (config_setting_lookup_int(c->cfg, "baseaddr_axi4", &baseaddr_axi4)) - fifo->baseaddr_axi4 = baseaddr_axi4; - else - fifo->baseaddr_axi4 = -1; - - return 0; -} - -int fifo_reset(struct ip *c) -{ - XLlFifo_Reset(&c->fifo.inst); - - return 0; -} - -static struct ip_type ip = { - .vlnv = { "xilinx.com", "ip", "axi_fifo_mm_s", NULL }, - .init = fifo_init, - .parse = fifo_parse, - .reset = fifo_reset -}; - -REGISTER_IP_TYPE(&ip) \ No newline at end of file diff --git a/lib/fpga/ip.c b/lib/fpga/ip.c index d97c49cf2..cde0080d3 100644 --- a/lib/fpga/ip.c +++ b/lib/fpga/ip.c @@ -1,100 +1,40 @@ -#include -#include +/** FPGA IP component. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ #include #include "log.h" +#include "plugin.h" -#include "fpga/ip.h" -#include "fpga/intc.h" -#include "fpga/fifo.h" -#include "nodes/fpga.h" - -#include "config.h" - -struct list ip_types; /**< Table of existing FPGA IP core drivers */ - -struct ip * ip_vlnv_lookup(struct list *l, const char *vendor, const char *library, const char *name, const char *version) -{ - list_foreach(struct ip *c, l) { - if (ip_vlnv_match(c, vendor, library, name, version)) - return c; - } - - return NULL; -} - -int ip_vlnv_match(struct ip *c, const char *vendor, const char *library, const char *name, const char *version) -{ - return ((vendor && strcmp(c->vlnv.vendor, vendor)) || - (library && strcmp(c->vlnv.library, library)) || - (name && strcmp(c->vlnv.name, name)) || - (version && strcmp(c->vlnv.version, version))) ? 0 : 1; -} - -int ip_vlnv_parse(struct ip *c, const char *vlnv) -{ - char *tmp = strdup(vlnv); - - c->vlnv.vendor = strdup(strtok(tmp, ":")); - c->vlnv.library = strdup(strtok(NULL, ":")); - c->vlnv.name = strdup(strtok(NULL, ":")); - c->vlnv.version = strdup(strtok(NULL, ":")); - - free(tmp); - - return 0; -} - -int ip_init(struct ip *c) +int fpga_ip_init(struct fpga_ip *c, struct fpga_ip_type *vt) { int ret; + + assert(c->state == STATE_DESTROYED); + + c->_vt = vt; + c->_vd = alloc(vt->size); - ret = c->_vt && c->_vt->init ? c->_vt->init(c) : 0; + ret = c->_vt->init ? c->_vt->init(c) : 0; if (ret) - error("Failed to intialize IP core: %s", c->name); + return ret; - if (ret == 0) - c->state = IP_STATE_INITIALIZED; + c->state = STATE_INITIALIZED; debug(8, "IP Core %s initalized (%u)", c->name, ret); return ret; } -int ip_reset(struct 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) -{ - if (c->_vt && c->_vt->destroy) - c->_vt->destroy(c); - - free(c->vlnv.vendor); - free(c->vlnv.library); - free(c->vlnv.name); - free(c->vlnv.version); -} - -void ip_dump(struct 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, - c->baseaddr, c->irq, c->port); - - if (c->_vt && c->_vt->dump) - 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; long long baseaddr; + + assert(c->state != STATE_STARTED && c->state != STATE_DESTROYED); c->cfg = cfg; @@ -102,21 +42,6 @@ int ip_parse(struct ip *c, config_setting_t *cfg) if (!c->name) cerror(cfg, "IP is missing a name"); - 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); - if (ret) - cerror(cfg, "Failed to parse VLNV identifier"); - - /* Try to find matching IP type */ - list_foreach(struct ip_type *t, &ip_types) { - if (ip_vlnv_match(c, t->vlnv.vendor, t->vlnv.library, t->vlnv.name, t->vlnv.version)) { - c->_vt = t; - break; - } - } - /* Common settings */ if (config_setting_lookup_int64(cfg, "baseaddr", &baseaddr)) c->baseaddr = baseaddr; @@ -132,6 +57,97 @@ int ip_parse(struct ip *c, config_setting_t *cfg) ret = c->_vt && c->_vt->parse ? c->_vt->parse(c) : 0; if (ret) error("Failed to parse settings for IP core '%s'", c->name); + + c->state = STATE_PARSED; return 0; } + +int fpga_ip_start(struct fpga_ip *c) +{ + int ret; + + assert(c->state == STATE_CHECKED); + + ret = c->_vt->start ? c->_vt->start(c) : 0; + if (ret) + return ret; + + c->state = STATE_STARTED; + + return 0; +} + +int fpga_ip_stop(struct fpga_ip *c) +{ + int ret; + + assert(c->state == STATE_STARTED); + + ret = c->_vt->stop ? c->_vt->stop(c) : 0; + if (ret) + return ret; + + c->state = STATE_STOPPED; + + return 0; +} + +int fpga_ip_destroy(struct fpga_ip *c) +{ + int ret; + + assert(c->state != STATE_DESTROYED); + + fpga_vlnv_destroy(&c->vlnv); + + ret = c->_vt->destroy ? c->_vt->destroy(c) : 0; + if (ret) + return ret; + + c->state = STATE_DESTROYED; + + free(c->_vd); + + return 0; +} + +int fpga_ip_reset(struct fpga_ip *c) +{ + debug(3, "Reset IP core: %s", c->name); + + return c->_vt->reset ? c->_vt->reset(c) : 0; +} + +void fpga_ip_dump(struct fpga_ip *c) +{ + assert(c->state != STATE_DESTROYED); + + 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, + c->baseaddr, c->irq, c->port); + + if (c->_vt->dump) + c->_vt->dump(c); +} + +struct fpga_ip_type * fpga_ip_type_lookup(const char *vstr) +{ + int ret; + + struct fpga_vlnv vlnv; + + ret = fpga_vlnv_parse(&vlnv, vstr); + if (ret) + return NULL; + + /* Try to find matching IP type */ + for (size_t i = 0; i < list_length(&plugins); i++) { + struct plugin *p = list_at(&plugins, i); + + if (p->type == PLUGIN_TYPE_FPGA_IP && !fpga_vlnv_cmp(&vlnv, &p->ip.vlnv)) + return &p->ip; + } + + return NULL; +} \ No newline at end of file diff --git a/lib/fpga/ips/Makefile.inc b/lib/fpga/ips/Makefile.inc new file mode 100644 index 000000000..54f1d72eb --- /dev/null +++ b/lib/fpga/ips/Makefile.inc @@ -0,0 +1,6 @@ +# Enable VILLASfpga support when libxil is available +ifndef WITHOUT_FPGA +ifeq ($(shell pkg-config libxil; echo $$?),0) + LIB_SRCS += $(wildcard lib/fpga/ips/*.c) +endif +endif \ No newline at end of file diff --git a/lib/fpga/dft.c b/lib/fpga/ips/dft.c similarity index 69% rename from lib/fpga/dft.c rename to lib/fpga/ips/dft.c index 379385844..c4877ceb5 100644 --- a/lib/fpga/dft.c +++ b/lib/fpga/ips/dft.c @@ -2,16 +2,19 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel **********************************************************************************/ #include "log.h" -#include "fpga/ip.h" -#include "fpga/dft.h" +#include "plugin.h" -int dft_parse(struct ip *c) +#include "fpga/ip.h" +#include "fpga/card.h" +#include "fpga/ips/dft.h" + +int dft_parse(struct fpga_ip *c) { - struct dft *dft = &c->dft; + struct dft *dft = c->_vd; config_setting_t *cfg_harms; @@ -40,13 +43,16 @@ int dft_parse(struct ip *c) return 0; } -int dft_init(struct ip *c) +int dft_start(struct fpga_ip *c) { int ret; - struct dft *dft = &c->dft; + + struct fpga_card *f = c->card; + struct dft *dft = c->_vd; + 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); @@ -70,24 +76,42 @@ int dft_init(struct ip *c) return 0; } -void dft_destroy(struct ip *c) +int dft_stop(struct fpga_ip *c) { - struct dft *dft = &c->dft; + struct dft *dft = c->_vd; + XHls_dft *xdft = &dft->inst; XHls_dft_DisableAutoRestart(xdft); + + return 0; +} + +int dft_destroy(struct fpga_ip *c) +{ + struct dft *dft = c->_vd; if (dft->fharmonics) { free(dft->fharmonics); dft->fharmonics = NULL; } + + return 0; } -static struct ip_type ip = { - .vlnv = { "acs.eonerc.rwth-aachen.de", "hls", "hls_dft", NULL }, - .init = dft_init, - .destroy = dft_destroy, - .parse = dft_parse +static struct plugin p = { + .name = "Discrete Fourier Transform", + .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 }, + .type = FPGA_IP_TYPE_MATH, + .start = dft_start, + .stop = dft_stop, + .destroy = dft_destroy, + .parse = dft_parse, + .size = sizeof(struct dft) + } }; -REGISTER_IP_TYPE(&ip) \ No newline at end of file +REGISTER_PLUGIN(&p) \ No newline at end of file diff --git a/lib/fpga/dma.c b/lib/fpga/ips/dma.c similarity index 82% rename from lib/fpga/dma.c rename to lib/fpga/ips/dma.c index 3db127f2d..01deaa31c 100644 --- a/lib/fpga/dma.c +++ b/lib/fpga/ips/dma.c @@ -3,7 +3,7 @@ * These functions present a simpler interface to Xilinx' DMA driver (XAxiDma_*) * * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel **********************************************************************************/ #include @@ -11,11 +11,13 @@ #include #include -#include - +#include "log.h" +#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) { @@ -33,9 +35,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) { @@ -49,18 +53,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->vfio_device.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->vfio_device.group->container, (uint64_t) mem->base_virt, (uint64_t) mem->base_phys, mem->len); if (ret) return ret; @@ -71,7 +75,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; @@ -94,9 +98,11 @@ 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; + struct dma *dma = c->_vd; + + XAxiDma *xdma = &dma->inst; debug(25, "DMA write: dmac=%s buf=%p len=%#zx", c->name, buf, len); @@ -105,9 +111,11 @@ 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; + struct dma *dma = c->_vd; + + XAxiDma *xdma = &dma->inst; debug(25, "DMA read: dmac=%s buf=%p len=%#zx", c->name, buf, len); @@ -116,10 +124,12 @@ 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; - + struct dma *dma = c->_vd; + + XAxiDma *xdma = &dma->inst; + debug(25, "DMA read complete: dmac=%s", c->name); return xdma->HasSg @@ -127,10 +137,12 @@ 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; - + struct dma *dma = c->_vd; + + XAxiDma *xdma = &dma->inst; + debug(25, "DMA write complete: dmac=%s", c->name); return xdma->HasSg @@ -138,11 +150,13 @@ 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; - XAxiDma *xdma = &c->dma.inst; + struct dma *dma = c->_vd; + + XAxiDma *xdma = &dma->inst; XAxiDma_BdRing *ring = XAxiDma_GetTxRing(xdma); XAxiDma_Bd *bds, *bd; @@ -213,11 +227,13 @@ 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; - XAxiDma *xdma = &c->dma.inst; + struct dma *dma = c->_vd; + + XAxiDma *xdma = &dma->inst; XAxiDma_BdRing *ring = XAxiDma_GetRxRing(xdma); XAxiDma_Bd *bds, *bd; @@ -281,9 +297,11 @@ 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; + struct dma *dma = c->_vd; + + XAxiDma *xdma = &dma->inst; XAxiDma_BdRing *ring = XAxiDma_GetTxRing(xdma); XAxiDma_Bd *bds; @@ -310,9 +328,11 @@ 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; + struct dma *dma = c->_vd; + + XAxiDma *xdma = &dma->inst; XAxiDma_BdRing *ring = XAxiDma_GetRxRing(xdma); XAxiDma_Bd *bds, *bd; @@ -362,9 +382,11 @@ 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; + struct dma *dma = c->_vd; + + XAxiDma *xdma = &dma->inst; XAxiDma_BdRing *ring = XAxiDma_GetRxRing(xdma); /* Checks */ @@ -398,9 +420,11 @@ 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; + struct dma *dma = c->_vd; + + XAxiDma *xdma = &dma->inst; XAxiDma_BdRing *ring = XAxiDma_GetTxRing(xdma); /* Checks */ @@ -435,9 +459,11 @@ 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; + struct dma *dma = c->_vd; + + XAxiDma *xdma = &dma->inst; XAxiDma_BdRing *ring = XAxiDma_GetRxRing(xdma); while (!(XAxiDma_IntrGetIrq(xdma, XAXIDMA_DEVICE_TO_DMA) & XAXIDMA_IRQ_IOC_MASK)) @@ -456,9 +482,11 @@ 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; + struct dma *dma = c->_vd; + + XAxiDma *xdma = &dma->inst; XAxiDma_BdRing *ring = XAxiDma_GetTxRing(xdma); while (!(XAxiDma_IntrGetIrq(xdma, XAXIDMA_DMA_TO_DEVICE) & XAXIDMA_IRQ_IOC_MASK)) @@ -532,10 +560,11 @@ static int dma_init_rings(XAxiDma *xdma, struct dma_mem *bd) return 0; } -int dma_init(struct ip *c) +int dma_start(struct fpga_ip *c) { int ret, sg; - struct dma *dma = &c->dma; + struct dma *dma = c->_vd; + XAxiDma *xdma = &dma->inst; /* Guess DMA type */ @@ -587,17 +616,26 @@ 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); + struct dma *dma = c->_vd; + + XAxiDma_Reset(&dma->inst); return 0; } -static struct ip_type ip = { - .vlnv = { "xilinx.com", "ip", "axi_dma", NULL }, - .init = dma_init, - .reset = dma_reset +static struct plugin p = { + .name = "Xilinx's AXI4 Direct Memory Access Controller", + .description = "Transfer data streams between VILLASnode and VILLASfpga", + .type = PLUGIN_TYPE_FPGA_IP, + .ip = { + .vlnv = { "xilinx.com", "ip", "axi_dma", NULL }, + .type = FPGA_IP_TYPE_DM_DMA, + .init = dma_start, + .reset = dma_reset, + .size = sizeof(struct dma) + } }; -REGISTER_IP_TYPE(&ip) \ No newline at end of file +REGISTER_PLUGIN(&p) \ No newline at end of file diff --git a/lib/fpga/ips/fifo.c b/lib/fpga/ips/fifo.c new file mode 100644 index 000000000..cbcb51303 --- /dev/null +++ b/lib/fpga/ips/fifo.c @@ -0,0 +1,132 @@ +/** FIFO related helper functions + * + * These functions present a simpler interface to Xilinx' FIFO driver (XLlFifo_*) + * + * @author Steffen Vogel + * @copyright 2017, Steffen Vogel + **********************************************************************************/ + +#include + +#include "utils.h" +#include "plugin.h" + +#include "fpga/ip.h" +#include "fpga/card.h" +#include "fpga/ips/fifo.h" +#include "fpga/ips/intc.h" + +int fifo_start(struct fpga_ip *c) +{ + int ret; + + struct fpga_card *f = c->card; + struct fifo *fifo = c->_vd; + + XLlFifo *xfifo = &fifo->inst; + XLlFifo_Config fifo_cfg = { + .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 */ + }; + + ret = XLlFifo_CfgInitialize(xfifo, &fifo_cfg, (uintptr_t) c->card->map + c->baseaddr); + if (ret != XST_SUCCESS) + return -1; + + XLlFifo_IntEnable(xfifo, XLLF_INT_RC_MASK); /* Receive complete IRQ */ + + return 0; +} + +int fifo_stop(struct fpga_ip *c) +{ + struct fifo *fifo = c->_vd; + + XLlFifo *xfifo = &fifo->inst; + + XLlFifo_IntDisable(xfifo, XLLF_INT_RC_MASK); /* Receive complete IRQ */ + + return 0; +} + +ssize_t fifo_write(struct fpga_ip *c, char *buf, size_t len) +{ + struct fifo *fifo = c->_vd; + + XLlFifo *xllfifo = &fifo->inst; + + uint32_t tdfv; + + tdfv = XLlFifo_TxVacancy(xllfifo); + if (tdfv < len) + return -1; + + XLlFifo_Write(xllfifo, buf, len); + XLlFifo_TxSetLen(xllfifo, len); + + return len; +} + +ssize_t fifo_read(struct fpga_ip *c, char *buf, size_t len) +{ + struct fifo *fifo = c->_vd; + + XLlFifo *xllfifo = &fifo->inst; + + size_t nextlen = 0; + uint32_t rxlen; + + while (!XLlFifo_IsRxDone(xllfifo)) + intc_wait(c->card->intc, c->irq); + XLlFifo_IntClear(xllfifo, XLLF_INT_RC_MASK); + + /* Get length of next frame */ + rxlen = XLlFifo_RxGetLen(xllfifo); + nextlen = MIN(rxlen, len); + + /* Read from FIFO */ + XLlFifo_Read(xllfifo, buf, nextlen); + + return nextlen; +} + +int fifo_parse(struct fpga_ip *c) +{ + struct fifo *fifo = c->_vd; + + int baseaddr_axi4; + + if (config_setting_lookup_int(c->cfg, "baseaddr_axi4", &baseaddr_axi4)) + fifo->baseaddr_axi4 = baseaddr_axi4; + else + fifo->baseaddr_axi4 = -1; + + return 0; +} + +int fifo_reset(struct fpga_ip *c) +{ + struct fifo *fifo = c->_vd; + + XLlFifo_Reset(&fifo->inst); + + return 0; +} + +static struct plugin p = { + .name = "Xilinx's AXI4 FIFO data mover", + .description = "", + .type = PLUGIN_TYPE_FPGA_IP, + .ip = { + .vlnv = { "xilinx.com", "ip", "axi_fifo_mm_s", NULL }, + .type = FPGA_IP_TYPE_DM_FIFO, + .start = fifo_start, + .stop = fifo_stop, + .parse = fifo_parse, + .reset = fifo_reset, + .size = sizeof(struct fifo) + } +}; + +REGISTER_PLUGIN(&p) \ No newline at end of file diff --git a/lib/fpga/intc.c b/lib/fpga/ips/intc.c similarity index 71% rename from lib/fpga/intc.c rename to lib/fpga/ips/intc.c index 1c590a81b..7601a8025 100644 --- a/lib/fpga/intc.c +++ b/lib/fpga/ips/intc.c @@ -1,36 +1,41 @@ /** AXI-PCIe Interrupt controller * * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel **********************************************************************************/ #include #include "config.h" #include "log.h" +#include "plugin.h" + #include "nodes/fpga.h" + #include "kernel/vfio.h" #include "kernel/kernel.h" -#include "fpga/ip.h" -#include "fpga/intc.h" -int intc_init(struct ip *c) +#include "fpga/ip.h" +#include "fpga/card.h" +#include "fpga/ips/intc.h" + +int intc_start(struct fpga_ip *c) { int ret; - struct fpga *f = c->card; - struct intc *intc = &c->intc; + struct fpga_card *f = c->card; + struct intc *intc = c->_vd; uintptr_t base = (uintptr_t) f->map + c->baseaddr; if (c != f->intc) error("There can be only one interrupt controller per FPGA"); - intc->num_irqs = vfio_pci_msi_init(&f->vd, intc->efds); + intc->num_irqs = vfio_pci_msi_init(&f->vfio_device, intc->efds); if (intc->num_irqs < 0) return -1; - ret = vfio_pci_msi_find(&f->vd, intc->nos); + ret = vfio_pci_msi_find(&f->vfio_device, intc->nos); if (ret) return -2; @@ -56,18 +61,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 intc *intc = &c->intc; + struct fpga_card *f = c->card; + struct intc *intc = c->_vd; - vfio_pci_msi_deinit(&f->vd, intc->efds); + vfio_pci_msi_deinit(&f->vfio_device, 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 intc *intc = &c->intc; - struct fpga *f = c->card; + struct fpga_card *f = c->card; + struct intc *intc = c->_vd; uint32_t ier, imr; uintptr_t base = (uintptr_t) f->map + c->baseaddr; @@ -102,9 +109,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); @@ -114,10 +121,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 intc *intc = &c->intc; - struct fpga *f = c->card; + struct fpga_card *f = c->card; + struct intc *intc = c->_vd; uintptr_t base = (uintptr_t) f->map + c->baseaddr; @@ -143,10 +150,17 @@ uint64_t intc_wait(struct ip *c, int irq) } } -static struct ip_type ip = { - .vlnv = { "acs.eonerc.rwth-aachen.de", "user", "axi_pcie_intc", NULL }, - .init = intc_init, - .destroy = intc_destroy +static struct plugin p = { + .name = "Xilinx's programmable interrupt controller", + .description = "", + .type = PLUGIN_TYPE_FPGA_IP, + .ip = { + .vlnv = { "acs.eonerc.rwth-aachen.de", "user", "axi_pcie_intc", NULL }, + .type = FPGA_IP_TYPE_MISC, + .start = intc_start, + .destroy = intc_destroy, + .size = sizeof(struct intc) + } }; -REGISTER_IP_TYPE(&ip) +REGISTER_PLUGIN(&p) \ No newline at end of file diff --git a/lib/fpga/model.c b/lib/fpga/ips/model.c similarity index 76% rename from lib/fpga/model.c rename to lib/fpga/ips/model.c index cb4188835..1eb2707a1 100644 --- a/lib/fpga/model.c +++ b/lib/fpga/ips/model.c @@ -1,7 +1,7 @@ /** Interface to Xilinx System Generator Models via PCIe * * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel *********************************************************************************/ #include @@ -9,21 +9,27 @@ #include #include -#include -#include +#include "utils.h" +#include "log.h" +#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) @@ -127,17 +133,17 @@ 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 *m = c->_vd; struct model_param p; config_setting_t *cfg_params, *cfg_param; if (strcmp(c->vlnv.library, "hls") == 0) - c->model.type = MODEL_TYPE_HLS; + m->type = MODEL_TYPE_HLS; else if (strcmp(c->vlnv.library, "sysgen") == 0) - c->model.type = MODEL_TYPE_XSG; + m->type = MODEL_TYPE_XSG; else cerror(c->cfg, "Invalid model type: %s", c->vlnv.library); @@ -185,21 +191,24 @@ 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; + + struct model *m = c->_vd; 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; /* Set default values for parameters */ - list_foreach(struct model_param *p, &m->parameters) { + for (size_t i = 0; i < list_length(&m->parameters); i++) { + struct model_param *p = list_at(&m->parameters, i); + p->ip = c; if (p->direction == MODEL_PARAM_IN) { @@ -214,27 +223,31 @@ 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; + struct model *m = c->_vd; list_destroy(&m->parameters, (dtor_cb_t) model_param_destroy, true); list_destroy(&m->infos, (dtor_cb_t) model_info_destroy, true); 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; + struct model *m = c->_vd; const char *param_type[] = { "UFix", "Fix", "Float", "Boolean" }; const char *parameter_dirs[] = { "In", "Out", "In/Out" }; { INDENT info("Parameters:"); - list_foreach(struct model_param *p, &m->parameters) { INDENT + for (size_t i = 0; i < list_length(&m->parameters); i++) { INDENT + struct model_param *p = list_at(&m->parameters, i); + if (p->direction == MODEL_PARAM_IN) info("%#jx: %s (%s) = %.3f %s %u", p->offset, @@ -253,7 +266,9 @@ void model_dump(struct ip *c) } info("Infos:"); - list_foreach(struct model_info *i, &m->infos) { INDENT + for (size_t j = 0; j < list_length(&m->infos); j++) { INDENT + struct model_info *i = list_at(&m->infos, j); + info("%s: %s", i->field, i->value); } } @@ -261,7 +276,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); @@ -287,7 +302,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); @@ -312,9 +327,9 @@ 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 *m = c->_vd; struct model_param *p = alloc(sizeof(struct model_param)); p->name = strdup(name); @@ -324,9 +339,9 @@ 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 *m = c->_vd; struct model_param *p; p = list_lookup(&m->parameters, name); @@ -351,21 +366,35 @@ int model_param_update(struct model_param *p, struct model_param *u) return 0; } -static struct ip_type ip_hls = { - .vlnv = { NULL, "hls", NULL, NULL }, - .init = model_init, - .destroy = model_destroy, - .dump = model_dump, - .parse = model_parse +static struct plugin p_hls = { + .name = "Xilinx High Level Synthesis (HLS) model", + .description = "", + .type = PLUGIN_TYPE_FPGA_IP, + .ip = { + .vlnv = { NULL, "hls", NULL, NULL }, + .type = FPGA_IP_TYPE_MODEL, + .init = model_init, + .destroy = model_destroy, + .dump = model_dump, + .parse = model_parse + } }; -static struct ip_type ip_xsg = { - .vlnv = { NULL, "sysgen", NULL, NULL }, - .init = model_init, - .destroy = model_destroy, - .dump = model_dump, - .parse = model_parse +REGISTER_PLUGIN(&p_hls) + +static struct plugin p_sysgen = { + .name = "Xilinx System Generator for DSP (XSG) model", + .description = "", + .type = PLUGIN_TYPE_FPGA_IP, + .ip = { + .vlnv = { NULL, "sysgen", NULL, NULL }, + .type = FPGA_IP_TYPE_MODEL, + .init = model_init, + .destroy = model_destroy, + .dump = model_dump, + .parse = model_parse, + .size = sizeof(struct model) + } }; -REGISTER_IP_TYPE(&ip_hls) -REGISTER_IP_TYPE(&ip_xsg) \ No newline at end of file +REGISTER_PLUGIN(&p_sysgen) diff --git a/lib/fpga/rtds_axis.c b/lib/fpga/ips/rtds_axis.c similarity index 76% rename from lib/fpga/rtds_axis.c rename to lib/fpga/ips/rtds_axis.c index 3cae5c65f..76f11f6e6 100644 --- a/lib/fpga/rtds_axis.c +++ b/lib/fpga/ips/rtds_axis.c @@ -1,18 +1,20 @@ /** Driver for AXI Stream wrapper around RTDS_InterfaceModule (rtds_axis ) * * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel **********************************************************************************/ #include #include "log.h" #include "utils.h" +#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); @@ -39,7 +41,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]; @@ -47,9 +49,16 @@ double rtds_axis_dt(struct ip *c) return (dt == 0xFFFF) ? -1.0 : (double) dt / RTDS_HZ; } -static struct ip_type ip = { - .vlnv = { "acs.eonerc.rwth-aachen.de", "user", "rtds_axis", NULL }, - .dump = rtds_axis_dump +static struct plugin p = { + .name = "RTDS's AXI4-Stream - GTFPGA interface", + .description = "", + .type = PLUGIN_TYPE_FPGA_IP, + .ip = { + .vlnv = { "acs.eonerc.rwth-aachen.de", "user", "rtds_axis", NULL }, + .type = FPGA_IP_TYPE_INTERFACE, + .dump = rtds_axis_dump, + .size = 0 + } }; -REGISTER_IP_TYPE(&ip) \ No newline at end of file +REGISTER_PLUGIN(&p) \ No newline at end of file diff --git a/lib/fpga/switch.c b/lib/fpga/ips/switch.c similarity index 75% rename from lib/fpga/switch.c rename to lib/fpga/ips/switch.c index 082713c2b..e9ca582ce 100644 --- a/lib/fpga/switch.c +++ b/lib/fpga/ips/switch.c @@ -3,19 +3,23 @@ * These functions present a simpler interface to Xilinx' AXI Stream switch driver (XAxis_Switch_*) * * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel **********************************************************************************/ #include "list.h" #include "log.h" -#include "fpga/switch.h" -#include "fpga/ip.h" +#include "plugin.h" -int switch_init(struct ip *c) +#include "fpga/ip.h" +#include "fpga/card.h" +#include "fpga/ips/switch.h" + +int switch_start(struct fpga_ip *c) { int ret; - struct sw *sw = &c->sw; - struct fpga *f = c->card; + + struct fpga_card *f = c->card; + struct sw *sw = c->_vd; XAxis_Switch *xsw = &sw->inst; @@ -25,7 +29,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 }; @@ -38,22 +42,25 @@ 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; + struct sw *sw = c->_vd; XAxis_Switch *xsw = &sw->inst; XAxisScr_RegUpdateDisable(xsw); XAxisScr_MiPortDisableAll(xsw); - list_foreach(struct sw_path *p, &sw->paths) { - struct ip *mi, *si; + for (size_t i = 0; i < list_length(&sw->paths); i++) { + struct sw_path *p = list_at(&sw->paths, i); + struct fpga_ip *mi, *si; mi = list_lookup(&c->card->ips, p->out); si = list_lookup(&c->card->ips, p->in); @@ -71,16 +78,19 @@ 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; + struct sw *sw = c->_vd; list_destroy(&sw->paths, NULL, true); + + return 0; } -int switch_parse(struct ip *c) +int switch_parse(struct fpga_ip *c) { - struct sw *sw = &c->sw; + struct fpga_card *f = c->card; + struct sw *sw = c->_vd; list_init(&sw->paths); @@ -89,7 +99,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 */ @@ -129,9 +139,9 @@ 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; + struct sw *sw = c->_vd; XAxis_Switch *xsw = &sw->inst; uint32_t mux, port; @@ -165,9 +175,9 @@ 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; + struct sw *sw = c->_vd; XAxis_Switch *xsw = &sw->inst; if (!XAxisScr_IsMiPortEnabled(xsw, mi->port, si->port)) @@ -178,11 +188,18 @@ int switch_disconnect(struct ip *c, struct ip *mi, struct ip *si) return 0; } -static struct ip_type ip = { - .vlnv = { "xilinx.com", "ip", "axis_interconnect", NULL }, - .init = switch_init, - .destroy = switch_destroy, - .parse = switch_parse +static struct plugin p = { + .name = "Xilinx's AXI4-Stream switch", + .description = "", + .type = PLUGIN_TYPE_FPGA_IP, + .ip = { + .vlnv = { "xilinx.com", "ip", "axis_interconnect", NULL }, + .type = FPGA_IP_TYPE_MISC, + .start = switch_start, + .destroy = switch_destroy, + .parse = switch_parse, + .size = sizeof(struct sw) + } }; -REGISTER_IP_TYPE(&ip) \ No newline at end of file +REGISTER_PLUGIN(&p) \ No newline at end of file diff --git a/lib/fpga/timer.c b/lib/fpga/ips/timer.c similarity index 54% rename from lib/fpga/timer.c rename to lib/fpga/ips/timer.c index 0d1ebc17d..21916c089 100644 --- a/lib/fpga/timer.c +++ b/lib/fpga/ips/timer.c @@ -4,18 +4,20 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel **********************************************************************************/ #include "config.h" +#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_start(struct fpga_ip *c) { - struct timer *tmr = &c->timer; - struct fpga *f = c->card; + struct fpga_card *f = c->card; + struct timer *tmr = c->_vd; XTmrCtr *xtmr = &tmr->inst; XTmrCtr_Config xtmr_cfg = { @@ -29,9 +31,16 @@ int timer_init(struct ip *c) return 0; } -static struct ip_type ip = { - .vlnv = { "xilinx.com", "ip", "axi_timer", NULL }, - .init = timer_init +static struct plugin p = { + .name = "Xilinx's programmable timer / counter", + .description = "", + .type = PLUGIN_TYPE_FPGA_IP, + .ip = { + .vlnv = { "xilinx.com", "ip", "axi_timer", NULL }, + .type = FPGA_IP_TYPE_MISC, + .start = timer_start, + .size = sizeof(struct timer) + } }; -REGISTER_IP_TYPE(&ip) \ No newline at end of file +REGISTER_PLUGIN(&p) \ No newline at end of file diff --git a/lib/fpga/vlnv.c b/lib/fpga/vlnv.c new file mode 100644 index 000000000..5021a9b88 --- /dev/null +++ b/lib/fpga/vlnv.c @@ -0,0 +1,48 @@ +/** Vendor, Library, Name, Version (VLNV) tag + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#include +#include + +#include "fpga/vlnv.h" +#include "fpga/ip.h" + +struct fpga_ip * fpga_vlnv_lookup(struct list *l, struct fpga_vlnv *v) +{ + return (struct fpga_ip *) list_search(l, (cmp_cb_t) fpga_vlnv_cmp, v); +} + +int fpga_vlnv_cmp(struct fpga_vlnv *a, struct fpga_vlnv *b) +{ + return ((!a->vendor || !b->vendor || !strcmp(a->vendor, b->vendor )) && + (!a->library || !b->library || !strcmp(a->library, b->library)) && + (!a->name || !b->name || !strcmp(a->name, b->name )) && + (!a->version || !b->version || !strcmp(a->version, b->version))) ? 0 : 1; +} + +int fpga_vlnv_parse(struct fpga_vlnv *c, const char *vlnv) +{ + char *tmp = strdup(vlnv); + + c->vendor = strdup(strtok(tmp, ":")); + c->library = strdup(strtok(NULL, ":")); + c->name = strdup(strtok(NULL, ":")); + c->version = strdup(strtok(NULL, ":")); + + free(tmp); + + return 0; +} + +int fpga_vlnv_destroy(struct fpga_vlnv *v) +{ + free(v->vendor); + free(v->library); + free(v->name); + free(v->version); + + return 0; +} diff --git a/lib/hist.c b/lib/hist.c index 834b56796..1f28bf721 100644 --- a/lib/hist.c +++ b/lib/hist.c @@ -1,7 +1,7 @@ /** Histogram functions. * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include @@ -17,20 +17,34 @@ #define VAL(h, i) ((h)->low + (i) * (h)->resolution) #define INDEX(h, v) round((v - (h)->low) / (h)->resolution) -void hist_create(struct hist *h, double low, double high, double resolution) +int hist_init(struct hist *h, double low, double high, double resolution) { h->low = low; h->high = high; h->resolution = resolution; - h->length = (high - low) / resolution; - h->data = alloc(h->length * sizeof(unsigned)); + + if (resolution > 0) { + h->length = (high - low) / resolution; + h->data = alloc(h->length * sizeof(hist_cnt_t)); + } + else { + h->length = 0; + h->data = NULL; + } hist_reset(h); + + return 0; } -void hist_destroy(struct hist *h) +int hist_destroy(struct hist *h) { - free(h->data); + if (h->data) { + free(h->data); + h->data = NULL; + } + + return 0; } void hist_put(struct hist *h, double value) @@ -50,7 +64,7 @@ void hist_put(struct hist *h, double value) h->higher++; else if (idx < 0) h->lower++; - else + else if (h->data != NULL) h->data[idx]++; h->total++; @@ -81,7 +95,8 @@ void hist_reset(struct hist *h) h->highest = DBL_MIN; h->lowest = DBL_MAX; - memset(h->data, 0, h->length * sizeof(unsigned)); + if (h->data) + memset(h->data, 0, h->length * sizeof(unsigned)); } double hist_mean(struct hist *h) @@ -99,13 +114,13 @@ double hist_stddev(struct hist *h) return sqrt(hist_var(h)); } -void hist_print(struct hist *h) +void hist_print(struct hist *h, int details) { INDENT - stats("Counted values: %u (%u between %f and %f)", h->total, h->total-h->higher-h->lower, h->high, h->low); + stats("Counted values: %ju (%ju between %f and %f)", h->total, h->total-h->higher-h->lower, h->high, h->low); stats("Highest: %f Lowest: %f", h->highest, h->lowest); stats("Mu: %f Sigma2: %f Sigma: %f", hist_mean(h), hist_var(h), hist_stddev(h)); - if (h->total - h->higher - h->lower > 0) { + if (details > 0 && h->total - h->higher - h->lower > 0) { char *buf = hist_dump(h); stats("Matlab: %s", buf); free(buf); @@ -133,11 +148,11 @@ void hist_plot(struct hist *h) for (int i = 0; i < h->length; i++) { double value = VAL(h, i); - int cnt = h->data[i]; + hist_cnt_t cnt = h->data[i]; int bar = HIST_HEIGHT * ((double) cnt / max); if (value > h->lowest || value < h->highest) - stats("%+9g | " "%5u" " | %.*s", value, cnt, bar, buf); + stats("%+9g | %5ju | %.*s", value, cnt, bar, buf); } } @@ -148,26 +163,78 @@ char * hist_dump(struct hist *h) strcatf(&buf, "[ "); for (int i = 0; i < h->length; i++) - strcatf(&buf, "%u ", h->data[i]); + strcatf(&buf, "%ju ", h->data[i]); strcatf(&buf, "]"); return buf; } -void hist_matlab(struct hist *h, FILE *f) +#ifdef WITH_JANSSON +json_t * hist_json(struct hist *h) { - char *buf = hist_dump(h); + json_t *json_buckets, *json_hist; - fprintf(f, "%lu = struct( ", time(NULL)); - fprintf(f, "'min', %f, 'max', %f, ", h->low, h->high); - fprintf(f, "'total', %u, higher', %u, 'lower', %u, ", h->total, h->higher, h->lower); - fprintf(f, "'highest', %f, 'lowest', %f, ", h->highest, h->lowest); - fprintf(f, "'mean', %f, ", hist_mean(h)); - fprintf(f, "'var', %f, ", hist_var(h)); - fprintf(f, "'stddev', %f, ", hist_stddev(h)); - fprintf(f, "'hist', %s ", buf); - fprintf(f, "),\n"); - - free(buf); + json_hist = json_pack("{ s: f, s: f, s: i, s: i, s: i, s: f, s: f, s: f, s: f, s: f }", + "low", h->low, + "high", h->high, + "total", h->total, + "higher", h->higher, + "lower", h->lower, + "highest", h->highest, + "lowest", h->lowest, + "mean", hist_mean(h), + "variance", hist_var(h), + "stddev", hist_stddev(h) + ); + + if (h->total - h->lower - h->higher > 0) { + json_buckets = json_array(); + + for (int i = 0; i < h->length; i++) + json_array_append(json_buckets, json_integer(h->data[i])); + + json_object_set(json_hist, "buckets", json_buckets); + } + + return json_hist; +} + +int hist_dump_json(struct hist *h, FILE *f) +{ + json_t *j = hist_json(h); + + int ret = json_dumpf(j, f, 0); + + json_decref(j); + + return ret; +} +#endif /* WITH_JANNSON */ + +int hist_dump_matlab(struct hist *h, FILE *f) +{ + fprintf(f, "struct("); + fprintf(f, "'low', %f, ", h->low); + fprintf(f, "'high', %f, ", h->high); + fprintf(f, "'total', %ju, ", h->total); + fprintf(f, "'higher', %ju, ", h->higher); + fprintf(f, "'lower', %ju, ", h->lower); + fprintf(f, "'highest', %f, ", h->highest); + fprintf(f, "'lowest', %f, ", h->lowest); + fprintf(f, "'mean', %f, ", hist_mean(h)); + fprintf(f, "'variance', %f, ", hist_var(h)); + fprintf(f, "'stddev', %f, ", hist_stddev(h)); + + if (h->total - h->lower - h->higher > 0) { + char *buf = hist_dump(h); + fprintf(f, "'buckets', %s", buf); + free(buf); + } + else + fprintf(f, "'buckets', zeros(1, %d)", h->length); + + fprintf(f, ")"); + + return 0; } diff --git a/lib/hook.c b/lib/hook.c new file mode 100644 index 000000000..4e6270130 --- /dev/null +++ b/lib/hook.c @@ -0,0 +1,189 @@ +/** Hook-releated functions. + * + * @author Steffen Vogel + * @copyright 2014-2016, Institute for Automation of Complex Power Systems, EONERC + * This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + *********************************************************************************/ + +#include +#include +#include + +#include "timing.h" +#include "config.h" +#include "msg.h" +#include "hook.h" +#include "path.h" +#include "utils.h" +#include "node.h" +#include "plugin.h" + +int hook_init(struct hook *h, struct hook_type *vt, struct path *p) +{ + int ret; + + assert(h->state == STATE_DESTROYED); + + h->priority = vt->priority; + h->path = p; + + h->_vt = vt; + h->_vd = alloc(vt->size); + + + ret = h->_vt->init ? h->_vt->init(h) : 0; + if (ret) + return ret; + + h->state = STATE_INITIALIZED; + + return 0; +} + +int hook_parse(struct hook *h, config_setting_t *cfg) +{ + int ret; + + assert(h->state != STATE_DESTROYED); + + config_setting_lookup_int(cfg, "priority", &h->priority); + + ret = h->_vt->parse ? h->_vt->parse(h, cfg) : 0; + if (ret) + return ret; + + h->state = STATE_PARSED; + + return 0; +} + +int hook_destroy(struct hook *h) +{ + int ret; + + assert(h->state != STATE_DESTROYED); + + ret = h->_vt->destroy ? h->_vt->destroy(h) : 0; + if (ret) + return ret; + + if (h->_vd) + free(h->_vd); + + h->state = STATE_DESTROYED; + + return 0; +} + +int hook_start(struct hook *h) +{ + return h->_vt->start ? h->_vt->start(h) : 0; +} + +int hook_stop(struct hook *h) +{ + return h->_vt->stop ? h->_vt->stop(h) : 0; +} + +int hook_periodic(struct hook *h) +{ + return h->_vt->periodic ? h->_vt->periodic(h) : 0; +} + +int hook_restart(struct hook *h) +{ + return h->_vt->restart ? h->_vt->restart(h) : 0; +} + +int hook_read(struct hook *h, struct sample *smps[], size_t *cnt) +{ + return h->_vt->read ? h->_vt->read(h, smps, cnt) : 0; +} + +size_t hook_read_list(struct list *hs, struct sample *smps[], size_t cnt) +{ + size_t ret; + + for (size_t i = 0; i < list_length(hs); i++) { + struct hook *h = list_at(hs, i); + + ret = hook_read(h, smps, &cnt); + if (ret || !cnt) + /* Abort hook processing if earlier hooks removed all samples + * or they returned something non-zero */ + break; + } + + return cnt; +} + +size_t hook_write_list(struct list *hs, struct sample *smps[], size_t cnt) +{ + size_t ret; + + for (size_t i = 0; i < list_length(hs); i++) { + struct hook *h = list_at(hs, i); + + ret = hook_write(h, smps, &cnt); + if (ret || !cnt) + /* Abort hook processing if earlier hooks removed all samples + * or they returned something non-zero */ + break; + } + + return cnt; +} + +int hook_write(struct hook *h, struct sample *smps[], size_t *cnt) +{ + return h->_vt->write ? h->_vt->write(h, smps, cnt) : 0; +} + +int hook_cmp_priority(const void *a, const void *b) +{ + struct hook *ha = (struct hook *) a; + struct hook *hb = (struct hook *) b; + + return ha->priority - hb->priority; +} + +int hook_parse_list(struct list *list, config_setting_t *cfg, struct path *o) +{ + struct hook h; + struct plugin *p; + + int ret, priority = 10; + + if (!config_setting_is_group(cfg)) + cerror(cfg, "Hooks must be configured with an object"); + + for (int i = 0; i < config_setting_length(cfg); i++) { + config_setting_t *cfg_hook = config_setting_get_elem(cfg, i); + + const char *name = config_setting_name(cfg_hook); + + p = plugin_lookup(PLUGIN_TYPE_HOOK, name); + if (!p) + continue; /* We ignore all non hook settings in this libconfig object setting */ + + if (!config_setting_is_group(cfg_hook)) + cerror(cfg_hook, "The 'hooks' setting must be an array of strings."); + + ret = hook_init(&h, &p->hook, o); + if (ret) + continue; + + /* If the user does not assign a priority, we will use the + * position of the hook section in the congiguration file. */ + h.priority = priority++; + + ret = hook_parse(&h, cfg_hook); + if (ret) + continue; + + list_push(list, memdup(&h, sizeof(h))); + } + + return 0; +} \ No newline at end of file diff --git a/lib/hooks.c b/lib/hooks.c deleted file mode 100644 index 688af8a70..000000000 --- a/lib/hooks.c +++ /dev/null @@ -1,68 +0,0 @@ -/** Hook-releated functions. - * - * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC - *********************************************************************************/ - -#include -#include - -#include "timing.h" -#include "config.h" -#include "msg.h" -#include "hooks.h" -#include "path.h" -#include "utils.h" -#include "node.h" - -struct list hooks; - -/* Those references can be used inside the hook callbacks after initializing them with hook_init() */ -struct list *hook_nodes = NULL; -struct list *hook_paths = NULL; -struct settings *hook_settings = NULL; - -void hook_init(struct list *nodes, struct list *paths, struct settings *set) -{ - hook_nodes = nodes; - hook_paths = paths; - hook_settings = set; -} - -int hooks_sort_priority(const void *a, const void *b) { - struct hook *ha = (struct hook *) a; - struct hook *hb = (struct hook *) b; - - return ha->priority - hb->priority; -} - -int hook_run(struct path *p, struct sample *smps[], size_t cnt, int when) -{ - list_foreach(struct hook *h, &p->hooks) { - if (h->type & when) { - debug(DBG_HOOK | 22, "Running hook when=%u '%s' prio=%u, cnt=%zu", when, h->name, h->priority, cnt); - - cnt = h->cb(p, h, when, smps, cnt); - if (cnt == 0) - break; - } - } - - return cnt; -} - -void * hook_storage(struct hook *h, int when, size_t len) -{ - switch (when) { - case HOOK_INIT: - h->_vd = alloc(len); - break; - - case HOOK_DEINIT: - free(h->_vd); - h->_vd = NULL; - break; - } - - return h->_vd; -} \ No newline at end of file diff --git a/lib/hooks/Makefile.inc b/lib/hooks/Makefile.inc new file mode 100644 index 000000000..488c96ade --- /dev/null +++ b/lib/hooks/Makefile.inc @@ -0,0 +1 @@ +LIB_SRCS += $(wildcard lib/hooks/*.c) \ No newline at end of file diff --git a/lib/hooks/convert.c b/lib/hooks/convert.c new file mode 100644 index 000000000..c801d1105 --- /dev/null +++ b/lib/hooks/convert.c @@ -0,0 +1,70 @@ +/** Convert hook. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +/** @addtogroup hooks Hook functions + * @{ + */ + +#include "hook.h" +#include "plugin.h" + +struct convert { + enum { + TO_FIXED, + TO_FLOAT + } mode; +}; + +static int convert_parse(struct hook *h, config_setting_t *cfg) +{ + struct convert *p = h->_vd; + + const char *mode; + + if (!config_setting_lookup_string(cfg, "mode", &mode)) + cerror(cfg, "Missing setting 'mode' for hook '%s'", plugin_name(h->_vt)); + + if (!strcmp(mode, "fixed")) + p->mode = TO_FIXED; + else if (!strcmp(mode, "float")) + p->mode = TO_FLOAT; + else + error("Invalid parameter '%s' for hook 'convert'", mode); + + return 0; +} + +static int convert_read(struct hook *h, struct sample *smps[], size_t *cnt) +{ + struct convert *p = h->_vd; + + for (int i = 0; i < *cnt; i++) { + for (int k = 0; k < smps[i]->length; k++) { + switch (p->mode) { + case TO_FIXED: smps[i]->data[k].i = smps[i]->data[k].f * 1e3; break; + case TO_FLOAT: smps[i]->data[k].f = smps[i]->data[k].i; break; + } + } + } + + return 0; +} + +static struct plugin p = { + .name = "convert", + .description = "Convert message from / to floating-point / integer", + .type = PLUGIN_TYPE_HOOK, + .hook = { + .priority = 99, + .parse = convert_parse, + .read = convert_read, + .size = sizeof(struct convert) + } +}; + +REGISTER_PLUGIN(&p) + +/** @} */ \ No newline at end of file diff --git a/lib/hooks/decimate.c b/lib/hooks/decimate.c new file mode 100644 index 000000000..462fbce9d --- /dev/null +++ b/lib/hooks/decimate.c @@ -0,0 +1,76 @@ +/** Decimate hook. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +/** @addtogroup hooks Hook functions + * @{ + */ + +#include "hook.h" +#include "plugin.h" + +struct decimate { + int ratio; + unsigned counter; +}; + +static int decimate_init(struct hook *h) +{ + struct decimate *p = h->_vd; + + p->counter = 0; + + return 0; +} + +static int decimate_parse(struct hook *h, config_setting_t *cfg) +{ + struct decimate *p = h->_vd; + + if (!cfg) + error("Missing configuration for hook: '%s'", plugin_name(h->_vt)); + + if (!config_setting_lookup_int(cfg, "ratio", &p->ratio)) + cerror(cfg, "Missing setting 'ratio' for hook '%s'", plugin_name(h->_vt)); + + return 0; +} + +static int decimate_read(struct hook *h, struct sample *smps[], size_t *cnt) +{ + struct decimate *p = h->_vd; + + int i, ok; + for (i = 0, ok = 0; i < *cnt; i++) { + if (p->counter++ % p->ratio == 0) { + struct sample *tmp; + + tmp = smps[ok]; + smps[ok++] = smps[i]; + smps[i] = tmp; + } + } + + *cnt = ok; + + return 0; +} + +static struct plugin p = { + .name = "decimate", + .description = "Downsamping by integer factor", + .type = PLUGIN_TYPE_HOOK, + .hook = { + .priority = 99, + .init = decimate_init, + .parse = decimate_parse, + .read = decimate_read, + .size = sizeof(struct decimate) + } +}; + +REGISTER_PLUGIN(&p) + +/** @} */ \ No newline at end of file diff --git a/lib/hooks/drop.c b/lib/hooks/drop.c new file mode 100644 index 000000000..d5b551430 --- /dev/null +++ b/lib/hooks/drop.c @@ -0,0 +1,73 @@ +/** Drop hook. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +/** @addtogroup hooks Hook functions + * @{ + */ + +#include "hook.h" +#include "plugin.h" +#include "stats.h" +#include "path.h" + +static int drop_read(struct hook *h, struct sample *smps[], size_t *cnt) +{ + int i, ok, dist; + + for (i = 0, ok = 0; i < *cnt; i++) { + h->last = smps[i]; + + if (h->prev) { + dist = h->last->sequence - (int32_t) h->prev->sequence; + if (dist <= 0) { + warn("Dropped sample: dist = %d, i = %d", dist, i); + if (h->path && h->path->stats) + stats_update(h->path->stats->delta, STATS_REORDERED, dist); + } + else { + struct sample *tmp; + + tmp = smps[i]; + smps[i] = smps[ok]; + smps[ok++] = tmp; + } + + /* To discard the first X samples in 'smps[]' we must + * shift them to the end of the 'smps[]' array. + * In case the hook returns a number 'ok' which is smaller than 'cnt', + * only the first 'ok' samples in 'smps[]' are accepted and further processed. + */ + } + else { + struct sample *tmp; + + tmp = smps[i]; + smps[i] = smps[ok]; + smps[ok++] = tmp; + } + + h->prev = h->last; + } + + *cnt = ok; + + return 0; +} + +static struct plugin p = { + .name = "drop", + .description = "Drop messages with reordered sequence numbers", + .type = PLUGIN_TYPE_HOOK, + .hook = { + .priority = 3, + .builtin = true, + .read = drop_read + } +}; + +REGISTER_PLUGIN(&p) + +/** @} */ \ No newline at end of file diff --git a/lib/hooks/fix_ts.c b/lib/hooks/fix_ts.c new file mode 100644 index 000000000..02fdd5672 --- /dev/null +++ b/lib/hooks/fix_ts.c @@ -0,0 +1,53 @@ +/** Fix timestamp hook. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +/** @addtogroup hooks Hook functions + * @{ + */ + +#include "hook.h" +#include "plugin.h" +#include "timing.h" + +int fix_ts_read(struct hook *h, struct sample *smps[], size_t *cnt) +{ + struct timespec now; + + now = time_now(); + + for (int i = 0; i < *cnt; i++) { + /* Check for missing receive timestamp + * Usually node_type::read() should update the receive timestamp. + * An example would be to use hardware timestamp capabilities of + * modern NICs. + */ + if ((smps[i]->ts.received.tv_sec == 0 && smps[i]->ts.received.tv_nsec == 0) || + (smps[i]->ts.received.tv_sec == -1 && smps[i]->ts.received.tv_nsec == -1)) + smps[i]->ts.received = now; + + /* Check for missing origin timestamp */ + if ((smps[i]->ts.origin.tv_sec == 0 && smps[i]->ts.origin.tv_nsec == 0) || + (smps[i]->ts.origin.tv_sec == -1 && smps[i]->ts.origin.tv_nsec == -1)) + smps[i]->ts.origin = now; + } + + return 0; +} + +static struct plugin p = { + .name = "fix_ts", + .description = "Update timestamps of sample if not set", + .type = PLUGIN_TYPE_HOOK, + .hook = { + .priority = 0, + .builtin = true, + .read = fix_ts_read, + } +}; + +REGISTER_PLUGIN(&p) + +/** @} */ \ No newline at end of file diff --git a/lib/hooks/hooks-internal.c b/lib/hooks/hooks-internal.c deleted file mode 100644 index 84858300a..000000000 --- a/lib/hooks/hooks-internal.c +++ /dev/null @@ -1,103 +0,0 @@ -/** Internal hook functions. - * - * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC - *********************************************************************************/ - -#include "hooks.h" -#include "timing.h" -#include "sample.h" -#include "path.h" -#include "utils.h" - -REGISTER_HOOK("fix_ts", "Update timestamps of sample if not set", 0, 0, hook_fix_ts, HOOK_INTERNAL | HOOK_READ) -int hook_fix_ts(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt) -{ - struct timespec now = time_now(); - - for (int i = 0; i < cnt; i++) { - /* Check for missing receive timestamp - * Usually node_type::read() should update the receive timestamp. - * An example would be to use hardware timestamp capabilities of - * modern NICs. - */ - if ((smps[i]->ts.received.tv_sec == 0 && smps[i]->ts.received.tv_nsec == 0) || - (smps[i]->ts.received.tv_sec == -1 && smps[i]->ts.received.tv_nsec == -1)) - smps[i]->ts.received = now; - - /* Check for missing origin timestamp */ - if ((smps[i]->ts.origin.tv_sec == 0 && smps[i]->ts.origin.tv_nsec == 0) || - (smps[i]->ts.origin.tv_sec == -1 && smps[i]->ts.origin.tv_nsec == -1)) - smps[i]->ts.origin = now; - } - - return cnt; -} - -REGISTER_HOOK("restart", "Call restart hooks for current path", 1, 1, hook_restart, HOOK_INTERNAL | HOOK_READ) -int hook_restart(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt) -{ - for (int i = 0; i < cnt; i++) { - h->last = smps[i]; - - if (h->prev) { - if (h->last->sequence == 0 && - h->prev->sequence <= UINT32_MAX - 32) { - warn("Simulation for path %s restarted (prev->seq=%u, current->seq=%u)", - path_name(p), h->prev->sequence, h->last->sequence); - - p->invalid = - p->skipped = - p->dropped = 0; - - hook_run(p, &smps[i], cnt - i, HOOK_PATH_RESTART); - } - } - - h->prev = h->last; - } - - return cnt; -} - -REGISTER_HOOK("drop", "Drop messages with reordered sequence numbers", 3, 1, hook_drop, HOOK_INTERNAL | HOOK_READ) -int hook_drop(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt) -{ - int i, ok, dist; - - for (i = 0, ok = 0; i < cnt; i++) { - h->last = smps[i]; - - if (h->prev) { - dist = h->last->sequence - (int32_t) h->prev->sequence; - if (dist <= 0) { - p->dropped++; - warn("Dropped sample: dist = %d, i = %d", dist, i); - } - else { - struct sample *tmp; - - tmp = smps[i]; - smps[i] = smps[ok]; - smps[ok++] = tmp; - } - - /* To discard the first X samples in 'smps[]' we must - * shift them to the end of the 'smps[]' array. - * In case the hook returns a number 'ok' which is smaller than 'cnt', - * only the first 'ok' samples in 'smps[]' are accepted and further processed. - */ - } - else { - struct sample *tmp; - - tmp = smps[i]; - smps[i] = smps[ok]; - smps[ok++] = tmp; - } - - h->prev = h->last; - } - - return ok; -} diff --git a/lib/hooks/hooks-other.c b/lib/hooks/hooks-other.c deleted file mode 100644 index c0b365bbf..000000000 --- a/lib/hooks/hooks-other.c +++ /dev/null @@ -1,163 +0,0 @@ -/** Other hook funktions. - * - * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC - *********************************************************************************/ - -#include -#include -#include -#include - -#include "hooks.h" -#include "timing.h" -#include "utils.h" -#include "sample.h" - -REGISTER_HOOK("print", "Print the message to stdout", 99, 0, hook_print, HOOK_READ) -int hook_print(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt) -{ - for (int i = 0; i < cnt; i++) - sample_fprint(stdout, smps[i], SAMPLE_ALL); - - return cnt; -} - -REGISTER_HOOK("ts", "Update timestamp of message with current time", 99, 0, hook_ts, HOOK_READ) -int hook_ts(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt) -{ - for (int i = 0; i < cnt; i++) - smps[i]->ts.origin = smps[i]->ts.received; - - return cnt; -} - -REGISTER_HOOK("convert", "Convert message from / to floating-point / integer", 99, 0, hook_convert, HOOK_STORAGE | HOOK_PARSE | HOOK_READ) -int hook_convert(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt) -{ - struct { - enum { - TO_FIXED, - TO_FLOAT - } mode; - } *private = hook_storage(h, when, sizeof(*private)); - - switch (when) { - case HOOK_PARSE: - if (!h->parameter) - error("Missing parameter for hook: '%s'", h->name); - - if (!strcmp(h->parameter, "fixed")) - private->mode = TO_FIXED; - else if (!strcmp(h->parameter, "float")) - private->mode = TO_FLOAT; - else - error("Invalid parameter '%s' for hook 'convert'", h->parameter); - break; - - case HOOK_READ: - for (int i = 0; i < cnt; i++) { - for (int j = 0; j < smps[0]->length; j++) { - switch (private->mode) { - case TO_FIXED: smps[i]->data[j].i = smps[i]->data[j].f * 1e3; break; - case TO_FLOAT: smps[i]->data[j].f = smps[i]->data[j].i; break; - } - } - } - break; - } - - return 0; -} - -REGISTER_HOOK("decimate", "Downsamping by integer factor", 99, 0, hook_decimate, HOOK_STORAGE | HOOK_PARSE | HOOK_READ) -int hook_decimate(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt) -{ - struct { - unsigned ratio; - unsigned counter; - } *private = hook_storage(h, when, sizeof(*private)); - - int ok; - - switch (when) { - case HOOK_PARSE: - if (!h->parameter) - error("Missing parameter for hook: '%s'", h->name); - - private->ratio = strtol(h->parameter, NULL, 10); - if (!private->ratio) - error("Invalid parameter '%s' for hook 'decimate'", h->parameter); - - private->counter = 0; - break; - - case HOOK_READ: - ok = 0; - for (int i = 0; i < cnt; i++) { - if (private->counter++ % private->ratio == 0) { - struct sample *tmp; - - tmp = smps[ok]; - smps[ok++] = smps[i]; - smps[i] = tmp; - } - } - return ok; - } - - return cnt; -} - -REGISTER_HOOK("skip_first", "Skip the first samples", 99, 0, hook_skip_first, HOOK_STORAGE | HOOK_PARSE | HOOK_READ | HOOK_PATH) -int hook_skip_first(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt) -{ - struct { - struct timespec skip; /**< Time to wait until first message is not skipped */ - struct timespec until; /**< Absolute point in time from where we accept samples. */ - } *private = hook_storage(h, when, sizeof(*private)); - - char *endptr; - double wait; - int i, ok; - - switch (when) { - case HOOK_PARSE: - if (!h->parameter) - error("Missing parameter for hook: '%s'", h->name); - - wait = strtof(h->parameter, &endptr); - if (h->parameter == endptr) - error("Invalid parameter '%s' for hook 'skip_first'", h->parameter); - - private->skip = time_from_double(wait); - break; - - case HOOK_PATH_RESTART: - case HOOK_PATH_STOP: - private->until = time_add(&smps[0]->ts.received, &private->skip); - break; - - case HOOK_READ: - for (i = 0, ok = 0; i < cnt; i++) { - if (time_delta(&private->until, &smps[i]->ts.received) > 0) { - struct sample *tmp; - - tmp = smps[i]; - smps[i] = smps[ok]; - smps[ok++] = tmp; - - } - - /* To discard the first X samples in 'smps[]' we must - * shift them to the end of the 'smps[]' array. - * In case the hook returns a number 'ok' which is smaller than 'cnt', - * only the first 'ok' samples in 'smps[]' are accepted and further processed. - */ - } - - return ok; - } - - return 0; -} \ No newline at end of file diff --git a/lib/hooks/hooks-stats.c b/lib/hooks/hooks-stats.c deleted file mode 100644 index 4a986f7f1..000000000 --- a/lib/hooks/hooks-stats.c +++ /dev/null @@ -1,137 +0,0 @@ -/** Statistic-related hook functions. - * - * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC - *********************************************************************************/ - -#include "hooks.h" -#include "sample.h" -#include "path.h" -#include "utils.h" -#include "timing.h" - -extern struct list *hook_nodes; - -void hook_stats_header() -{ - #define UNIT(u) "(" YEL(u) ")" - - stats("%-40s|%19s|%19s|%19s|%19s|%19s|%10s|", "Source " MAG("=>") " Destination", - "OWD" UNIT("S") " ", - "Rate" UNIT("p/S") " ", - "Drop" UNIT("p") " ", - "Skip" UNIT("p") " ", - "Inval" UNIT("p") " ", - "Overuns " - ); - line(); -} - -REGISTER_HOOK("stats", "Collect statistics for the current path", 2, 1, hook_stats, HOOK_STATS) -int hook_stats(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt) -{ - switch (when) { - case HOOK_INIT: - /** @todo Allow configurable bounds for histograms */ - hist_create(&p->hist.owd, 0, 1, 100e-3); - hist_create(&p->hist.gap_msg, 90e-3, 110e-3, 1e-3); - hist_create(&p->hist.gap_recv, 90e-3, 110e-3, 1e-3); - hist_create(&p->hist.gap_seq, -HIST_SEQ, +HIST_SEQ, 1); - break; - - case HOOK_READ: - for (int i = 0; i < cnt; i++) { - h->last = smps[i]; - - if (h->prev) { - int gap_seq = h->last->sequence - (int32_t) h->prev->sequence; - double owd = time_delta(&h->last->ts.origin, &h->last->ts.received); - double gap = time_delta(&h->prev->ts.origin, &h->last->ts.origin); - double gap_recv = time_delta(&h->prev->ts.received, &h->last->ts.received); - - hist_put(&p->hist.gap_msg, gap); - hist_put(&p->hist.gap_seq, gap_seq); - hist_put(&p->hist.owd, owd); - hist_put(&p->hist.gap_recv, gap_recv); - } - - h->prev = h->last; - } - break; - - case HOOK_PATH_STOP: - if (p->hist.owd.total) { info("One-way delay:"); hist_print(&p->hist.owd); } - if (p->hist.gap_recv.total){ info("Inter-message arrival time:"); hist_print(&p->hist.gap_recv); } - if (p->hist.gap_msg.total) { info("Inter-message ts gap:"); hist_print(&p->hist.gap_msg); } - if (p->hist.gap_seq.total) { info("Inter-message sequence number gaps:"); hist_print(&p->hist.gap_seq); } - break; - - case HOOK_DEINIT: - hist_destroy(&p->hist.owd); - hist_destroy(&p->hist.gap_msg); - hist_destroy(&p->hist.gap_recv); - hist_destroy(&p->hist.gap_seq); - break; - - case HOOK_PATH_RESTART: - hist_reset(&p->hist.owd); - hist_reset(&p->hist.gap_seq); - hist_reset(&p->hist.gap_msg); - hist_reset(&p->hist.gap_recv); - break; - - case HOOK_PERIODIC: - stats("%-40.40s|%10s|%10s|%10ju|%10ju|%10ju|%10ju|", path_name(p), "", "", - p->dropped, p->skipped, p->invalid, p->overrun); - break; - } - - return cnt; -} - -REGISTER_HOOK("stats_send", "Send path statistics to another node", 99, 0, hook_stats_send, HOOK_STORAGE | HOOK_PARSE | HOOK_PERIODIC | HOOK_PATH) -int hook_stats_send(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt) -{ - struct private { - struct node *dest; - int ratio; - } *private = hook_storage(h, when, sizeof(*private)); - - switch (when) { - case HOOK_PARSE: - if (!h->parameter) - error("Missing parameter for hook '%s'", h->name); - - if (!hook_nodes) - error("Missing reference to node list for hook '%s", h->name); - - private->dest = list_lookup(hook_nodes, h->parameter); - if (!private->dest) - error("Invalid destination node '%s' for hook '%s'", h->parameter, h->name); - - node_start(private->dest); - - break; - - case HOOK_PERIODIC: { - int i; - char buf[SAMPLE_LEN(16)]; - struct sample *smp = (struct sample *) buf; - - i = 0; - smp->data[i++].f = p->invalid; - smp->data[i++].f = p->skipped; - smp->data[i++].f = p->dropped; - smp->data[i++].f = p->overrun; - smp->data[i++].f = p->hist.owd.last, - smp->data[i++].f = 1.0 / p->hist.gap_msg.last; - smp->data[i++].f = 1.0 / p->hist.gap_recv.last; - smp->length = i; - - node_write(private->dest, &smp, 1); /* Send single message with statistics to destination node */ - break; - } - } - - return 0; -} \ No newline at end of file diff --git a/lib/hooks/map.c b/lib/hooks/map.c new file mode 100644 index 000000000..91af0d474 --- /dev/null +++ b/lib/hooks/map.c @@ -0,0 +1,97 @@ +/** Override a value of the sample with a header, timestamp or statistic value. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +/** @addtogroup hooks Hook functions + * @{ + */ + +#include "plugin.h" +#include "mapping.h" +#include "list.h" +#include "utils.h" +#include "path.h" + +struct map { + struct mapping mapping; + + struct stats *stats; +}; + +static int map_init(struct hook *h) +{ + struct map *p = h->_vd; + + return mapping_init(&p->mapping); +} + +static int map_destroy(struct hook *h) +{ + struct map *p = h->_vd; + + return mapping_destroy(&p->mapping); +} + +static int map_parse(struct hook *h, config_setting_t *cfg) +{ + struct map *p = h->_vd; + + int ret; + + config_setting_t *cfg_mapping; + + cfg_mapping = config_setting_lookup(cfg, "mapping"); + + if (!config_setting_is_array(cfg_mapping)) + return -1; + + ret = mapping_parse(&p->mapping, cfg_mapping); + if (ret) + return ret; + + return 0; +} + +static int map_read(struct hook *h, struct sample *smps[], size_t *cnt) +{ + int ret; + struct map *p = h->_vd; + struct sample *tmp[*cnt]; + + if (*cnt <= 0) + return 0; + + ret = sample_alloc(smps[0]->pool, tmp, *cnt); + if (ret != *cnt) + return ret; + + for (int i = 0; i < *cnt; i++) { + mapping_remap(&p->mapping, smps[i], tmp[i], NULL); + + SWAP(smps[i], tmp[i]); + } + + sample_free(tmp, *cnt); + + return 0; +} + +static struct plugin p = { + .name = "map", + .description = "Remap values and / or add data generated by this instace.", + .type = PLUGIN_TYPE_HOOK, + .hook = { + .priority = 99, + .init = map_init, + .destroy= map_destroy, + .parse = map_parse, + .read = map_read, + .size = sizeof(struct map) + } +}; + +REGISTER_PLUGIN(&p); + +/** @} */ \ No newline at end of file diff --git a/lib/hooks/print.c b/lib/hooks/print.c new file mode 100644 index 000000000..a4eec0f1c --- /dev/null +++ b/lib/hooks/print.c @@ -0,0 +1,89 @@ +/** Print hook. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +/** @addtogroup hooks Hook functions + * @{ + */ + +#include "hook.h" +#include "plugin.h" +#include "sample.h" + +struct print { + FILE *output; + const char *uri; +}; + +static int print_init(struct hook *h) +{ + struct print *p = h->_vd; + + p->output = stdout; + p->uri = NULL; + + return 0; +} + +static int print_start(struct hook *h) +{ + struct print *p = h->_vd; + + if (p->uri) { + p->output = fopen(p->uri, "w+"); + if (!p->output) + error("Failed to open file %s for writing", p->uri); + } + + return 0; +} + +static int print_stop(struct hook *h) +{ + struct print *p = h->_vd; + + if (p->uri) + fclose(p->output); + + return 0; +} + +static int print_parse(struct hook *h, config_setting_t *cfg) +{ + struct print *p = h->_vd; + + config_setting_lookup_string(cfg, "output", &p->uri); + + return 0; +} + +static int print_read(struct hook *h, struct sample *smps[], size_t *cnt) +{ + struct print *p = h->_vd; + + for (int i = 0; i < *cnt; i++) + sample_fprint(p->output, smps[i], SAMPLE_ALL); + + return 0; +} + +static struct plugin p = { + .name = "print", + .description = "Print the message to stdout", + .type = PLUGIN_TYPE_HOOK, + .hook = { + .priority = 99, + .init = print_init, + .parse = print_parse, + .start = print_start, + .stop = print_stop, + .read = print_read, + .size = sizeof(struct print) + } +}; + +REGISTER_PLUGIN(&p) + +/** @} */ \ No newline at end of file diff --git a/lib/hooks/restart.c b/lib/hooks/restart.c new file mode 100644 index 000000000..2f62304c2 --- /dev/null +++ b/lib/hooks/restart.c @@ -0,0 +1,56 @@ +/** Path restart hook. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +/** @addtogroup hooks Hook functions + * @{ + */ + +#include "hook.h" +#include "plugin.h" +#include "path.h" + +static int restart_read(struct hook *h, struct sample *smps[], size_t *cnt) +{ + assert(h->path); + + for (int i = 0; i < *cnt; i++) { + h->last = smps[i]; + + if (h->prev) { + if (h->last->sequence == 0 && + h->prev->sequence <= UINT32_MAX - 32) { + warn("Simulation for path %s restarted (prev->seq=%u, current->seq=%u)", + path_name(h->path), h->prev->sequence, h->last->sequence); + + /* Run restart hooks */ + for (size_t i = 0; i < list_length(&h->path->hooks); i++) { + struct hook *k = list_at(&h->path->hooks, i); + + hook_restart(k); + } + } + } + + h->prev = h->last; + } + + return 0; +} + +static struct plugin p = { + .name = "restart", + .description = "Call restart hooks for current path", + .type = PLUGIN_TYPE_HOOK, + .hook = { + .priority = 1, + .builtin = true, + .read = restart_read + } +}; + +REGISTER_PLUGIN(&p) + +/** @} */ \ No newline at end of file diff --git a/lib/hooks/shift_seq.c b/lib/hooks/shift_seq.c new file mode 100644 index 000000000..4e3133675 --- /dev/null +++ b/lib/hooks/shift_seq.c @@ -0,0 +1,52 @@ +/** Shift sequence number of samples + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +/** @addtogroup hooks Hook functions + * @{ + */ + +#include "hook.h" +#include "plugin.h" + +struct shift { + int offset; +}; + +static int shift_seq_parse(struct hook *h, config_setting_t *cfg) +{ + struct shift *p = h->_vd; + + if (!config_setting_lookup_int(cfg, "offset", &p->offset)) + cerror(cfg, "Missing setting 'offset' for hook '%s'", plugin_name(h->_vt)); + + return 0; +} + +static int shift_seq_read(struct hook *h, struct sample *smps[], size_t *cnt) +{ + struct shift *p = h->_vd; + + for (int i = 0; i < *cnt; i++) + smps[i]->sequence += p->offset; + + return 0; +} + +static struct plugin p = { + .name = "shift_seq", + .description = "Shift sequence number of samples", + .type = PLUGIN_TYPE_HOOK, + .hook = { + .priority = 99, + .parse = shift_seq_parse, + .read = shift_seq_read, + .size = sizeof(struct shift), + } +}; + +REGISTER_PLUGIN(&p) + +/** @} */ \ No newline at end of file diff --git a/lib/hooks/shift_ts.c b/lib/hooks/shift_ts.c new file mode 100644 index 000000000..612bbf0d5 --- /dev/null +++ b/lib/hooks/shift_ts.c @@ -0,0 +1,95 @@ +/** Shift timestamps of samples. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +/** @addtogroup hooks Hook functions + * @{ + */ + +#include "hook.h" +#include "plugin.h" +#include "timing.h" + +struct shift_ts { + struct timespec offset; + enum { + SHIFT_ORIGIN, + SHIFT_RECEIVED, + SHIFT_SENT, + } mode; +}; + +static int shift_ts_init(struct hook *h) +{ + struct shift_ts *p = h->_vd; + + p->mode = SHIFT_ORIGIN; /* Default mode */ + + return 0; +} + +static int shift_ts_parse(struct hook *h, config_setting_t *cfg) +{ + struct shift_ts *p = h->_vd; + + const char *mode; + + if (config_setting_lookup_string(cfg, "mode", &mode)) { + if (!strcmp(mode, "origin")) + p->mode = SHIFT_ORIGIN; + else if (!strcmp(mode, "received")) + p->mode = SHIFT_RECEIVED; + else if (!strcmp(mode, "sent")) + p->mode = SHIFT_SENT; + else + cerror(cfg, "Invalid mode parameter '%s' for hook '%s'", mode, plugin_name(h->_vt)); + } + + double offset; + if (!config_setting_lookup_float(cfg, "offset", &offset)) + cerror(cfg, "Missing setting 'offset' for hook '%s'", plugin_name(h->_vt)); + + p->offset = time_from_double(offset); + + return 0; +} + +static int shift_ts_read(struct hook *h, struct sample *smps[], size_t *cnt) +{ + struct shift_ts *p = h->_vd; + + for (int i = 0; i < *cnt; i++) { + struct sample *s = smps[i]; + struct timespec *ts; + + switch (p->mode) { + case SHIFT_ORIGIN: ts = &s->ts.origin; break; + case SHIFT_RECEIVED: ts = &s->ts.received; break; + case SHIFT_SENT: ts = &s->ts.sent; break; + default: return -1; + } + + *ts = time_add(ts, &p->offset); break; + } + + return 0; +} + +static struct plugin p = { + .name = "shift_ts", + .description = "Shift timestamps of samples", + .type = PLUGIN_TYPE_HOOK, + .hook = { + .priority = 99, + .init = shift_ts_init, + .parse = shift_ts_parse, + .read = shift_ts_read, + .size = sizeof(struct shift_ts) + } +}; + +REGISTER_PLUGIN(&p) + +/** @} */ \ No newline at end of file diff --git a/lib/hooks/skip_first.c b/lib/hooks/skip_first.c new file mode 100644 index 000000000..860acb8a7 --- /dev/null +++ b/lib/hooks/skip_first.c @@ -0,0 +1,136 @@ +/** Skip first hook. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +/** @addtogroup hooks Hook functions + * @{ + */ + +#include + +#include "hook.h" +#include "plugin.h" +#include "timing.h" + +struct skip_first { + enum { + HOOK_SKIP_FIRST_STATE_STARTED, /**< Path just started. First sample not received yet. */ + HOOK_SKIP_FIRST_STATE_SKIPPING, /**< First sample received. Skipping samples now. */ + HOOK_SKIP_FIRST_STATE_NORMAL, /**< All samples skipped. Normal operation. */ + } state; + enum { + HOOK_SKIP_MODE_SECONDS, + HOOK_SKIP_MODE_SAMPLES + } mode; + union { + struct { + struct timespec until; + struct timespec wait; /**< Absolute point in time from where we accept samples. */ + } seconds; + struct { + int until; + int wait; + } samples; + }; +}; + +static int skip_first_parse(struct hook *h, config_setting_t *cfg) +{ + struct skip_first *p = h->_vd; + + double seconds; + + if (config_setting_lookup_float(cfg, "seconds", &seconds)) { + p->seconds.wait = time_from_double(seconds); + p->mode = HOOK_SKIP_MODE_SECONDS; + } + else if (config_setting_lookup_int(cfg, "samples", &p->samples.wait)) { + p->mode = HOOK_SKIP_MODE_SAMPLES; + } + else + cerror(cfg, "Missing setting 'seconds' or 'samples' for hook '%s'", plugin_name(h->_vt)); + + return 0; +} + +static int skip_first_restart(struct hook *h) +{ + struct skip_first *p = h->_vd; + + p->state = HOOK_SKIP_FIRST_STATE_STARTED; + + return 0; +} + +static int skip_first_read(struct hook *h, struct sample *smps[], size_t *cnt) +{ + struct skip_first *p = h->_vd; + + if (p->state == HOOK_SKIP_FIRST_STATE_STARTED) { + switch (p->mode) { + case HOOK_SKIP_MODE_SAMPLES: + p->samples.until = smps[0]->sequence + p->samples.wait; + break; + + case HOOK_SKIP_MODE_SECONDS: + p->seconds.until = time_add(&smps[0]->ts.received, &p->seconds.wait); + break; + } + + p->state = HOOK_SKIP_FIRST_STATE_SKIPPING; + } + + int i, ok; + for (i = 0, ok = 0; i < *cnt; i++) { + bool skip; + switch (p->mode) { + case HOOK_SKIP_MODE_SAMPLES: + skip = p->samples.until >= smps[i]->sequence; + break; + + case HOOK_SKIP_MODE_SECONDS: + skip = time_delta(&p->seconds.until, &smps[i]->ts.received) < 0; + break; + default: + skip = false; + } + + if (!skip) { + struct sample *tmp; + + tmp = smps[i]; + smps[i] = smps[ok]; + smps[ok++] = tmp; + } + + /* To discard the first X samples in 'smps[]' we must + * shift them to the end of the 'smps[]' array. + * In case the hook returns a number 'ok' which is smaller than 'cnt', + * only the first 'ok' samples in 'smps[]' are accepted and further processed. + */ + } + + *cnt = ok; + + return 0; +} + +static struct plugin p = { + .name = "skip_first", + .description = "Skip the first samples", + .type = PLUGIN_TYPE_HOOK, + .hook = { + .priority = 99, + .parse = skip_first_parse, + .start = skip_first_restart, + .restart = skip_first_restart, + .read = skip_first_read, + .size = sizeof(struct skip_first) + } +}; + +REGISTER_PLUGIN(&p) + +/** @} */ \ No newline at end of file diff --git a/lib/hooks/stats.c b/lib/hooks/stats.c new file mode 100644 index 000000000..4de4ebf8a --- /dev/null +++ b/lib/hooks/stats.c @@ -0,0 +1,264 @@ +/** Statistic hooks. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +/** @addtogroup hooks Hook functions + * @{ + */ + +#include "hook.h" +#include "plugin.h" +#include "stats.h" +#include "path.h" + +struct stats_collect { + struct stats stats; + + enum stats_format format; + int verbose; + + FILE *output; + const char *uri; +}; + +static int stats_collect_init(struct hook *h) +{ + struct stats_collect *p = h->_vd; + + stats_init(&p->stats); + + /* Register statistic object to path. + * + * This allows the path code to update statistics. */ + if (h->path) + h->path->stats = &p->stats; + + /* Set default values */ + p->format = STATS_FORMAT_HUMAN; + p->verbose = 0; + p->uri = NULL; + p->output = stdout; + + return 0; +} + +static int stats_collect_destroy(struct hook *h) +{ + struct stats_collect *p = h->_vd; + + stats_destroy(&p->stats); + + return 0; +} + +static int stats_collect_start(struct hook *h) +{ + struct stats_collect *p = h->_vd; + + if (p->uri) { + p->output = fopen(p->uri, "w+"); + if (!p->output) + error("Failed to open file %s for writing", p->uri); + } + + return 0; +} + +static int stats_collect_stop(struct hook *h) +{ + struct stats_collect *p = h->_vd; + + stats_print(&p->stats, p->output, p->format, p->verbose); + + if (p->uri) + fclose(p->output); + + return 0; +} + +static int stats_collect_restart(struct hook *h) +{ + struct stats_collect *p = h->_vd; + + stats_reset(&p->stats); + + return 0; +} + +static int stats_collect_periodic(struct hook *h) +{ + struct stats_collect *p = h->_vd; + + stats_print_periodic(&p->stats, p->output, p->format, p->verbose, h->path); + + return 0; +} + +static int stats_collect_parse(struct hook *h, config_setting_t *cfg) +{ + struct stats_collect *p = h->_vd; + + const char *format; + if (config_setting_lookup_string(cfg, "format", &format)) { + if (!strcmp(format, "human")) + p->format = STATS_FORMAT_HUMAN; + else if (!strcmp(format, "json")) + p->format = STATS_FORMAT_JSON; + else if (!strcmp(format, "matlab")) + p->format = STATS_FORMAT_MATLAB; + else + cerror(cfg, "Invalid statistic output format: %s", format); + } + + config_setting_lookup_int(cfg, "verbose", &p->verbose); + config_setting_lookup_string(cfg, "output", &p->uri); + + return 0; +} + +static int stats_collect_read(struct hook *h, struct sample *smps[], size_t *cnt) +{ + struct stats_collect *p = h->_vd; + + stats_collect(p->stats.delta, smps, *cnt); + stats_commit(&p->stats, p->stats.delta); + + return 0; +} + +struct stats_send { + struct node *dest; + + enum { + STATS_SEND_MODE_PERIODIC, + STATS_SEND_MODE_READ + } mode; + + int decimation; +}; + +static int stats_send_init(struct hook *h) +{ + struct stats_send *p = h->_vd; + + p->decimation = 1; + p->mode = STATS_SEND_MODE_PERIODIC; + + return 0; +} + +static int stats_send_parse(struct hook *h, config_setting_t *cfg) +{ + struct stats_send *p = h->_vd; + + assert(h->path && h->path->super_node); + + const char *dest, *mode; + + if (config_setting_lookup_string(cfg, "destination", &dest)) { + p->dest = list_lookup(&h->path->super_node->nodes, dest); + if (!p->dest) + cerror(cfg, "Invalid destination node '%s' for hook '%s'", dest, plugin_name(h->_vt)); + } + else + cerror(cfg, "Missing setting 'destination' for hook '%s'", plugin_name(h->_vt)); + + if (config_setting_lookup_string(cfg, "destination", &mode)) { + if (!strcmp(mode, "periodic")) + p->mode = STATS_SEND_MODE_PERIODIC; + else if (!strcmp(mode, "read")) + p->mode = STATS_SEND_MODE_READ; + else + cerror(cfg, "Invalid value '%s' for setting 'mode' of hook '%s'", mode, plugin_name(h->_vt)); + } + + config_setting_lookup_int(cfg, "decimation", &p->decimation); + + return 0; +} + +static int stats_send_start(struct hook *h) +{ + struct stats_send *p = h->_vd; + + if (p->dest->state != STATE_STOPPED) + node_start(p->dest); + + return 0; +} + +static int stats_send_stop(struct hook *h) +{ + struct stats_send *p = h->_vd; + + if (p->dest->state != STATE_STOPPED) + node_stop(p->dest); + + return 0; +} + +static int stats_send_periodic(struct hook *h) +{ + struct stats_send *p = h->_vd; + + if (p->mode == STATS_SEND_MODE_PERIODIC) + stats_send(h->path->stats, p->dest); + + return 0; +} + +static int stats_send_read(struct hook *h, struct sample *smps[], size_t *cnt) +{ + struct stats_send *p = h->_vd; + + assert(h->path->stats); + + if (p->mode == STATS_SEND_MODE_READ) { + size_t processed = h->path->stats->histograms[STATS_OWD].total; + if (processed % p->decimation == 0) + stats_send(h->path->stats, p->dest); + } + + return 0; +} + +static struct plugin p1 = { + .name = "stats", + .description = "Collect statistics for the current path", + .type = PLUGIN_TYPE_HOOK, + .hook = { + .priority = 2, + .init = stats_collect_init, + .destroy= stats_collect_destroy, + .start = stats_collect_start, + .stop = stats_collect_stop, + .read = stats_collect_read, + .restart= stats_collect_restart, + .periodic= stats_collect_periodic, + .parse = stats_collect_parse, + .size = sizeof(struct stats_collect), + } +}; + +static struct plugin p2 = { + .name = "stats_send", + .description = "Send path statistics to another node", + .type = PLUGIN_TYPE_HOOK, + .hook = { + .priority = 99, + .init = stats_send_init, + .parse = stats_send_parse, + .start = stats_send_start, + .stop = stats_send_stop, + .periodic= stats_send_periodic, + .read = stats_send_read, + .size = sizeof(struct stats_send) + } +}; + +REGISTER_PLUGIN(&p1) +REGISTER_PLUGIN(&p2) + +/** @} */ \ No newline at end of file diff --git a/lib/hooks/ts.c b/lib/hooks/ts.c new file mode 100644 index 000000000..7e65f7f2b --- /dev/null +++ b/lib/hooks/ts.c @@ -0,0 +1,36 @@ +/** Timestamp hook. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +/** @addtogroup hooks Hook functions + * @{ + */ + +#include "hook.h" +#include "plugin.h" +#include "timing.h" + +static int ts_read(struct hook *h, struct sample *smps[], size_t *cnt) +{ + for (int i = 0; i < *cnt; i++) + smps[i]->ts.origin = smps[i]->ts.received; + + return 0; +} + +static struct plugin p = { + .name = "ts", + .description = "Overwrite origin timestamp of samples with receive timestamp", + .type = PLUGIN_TYPE_HOOK, + .hook = { + .priority = 99, + .read = ts_read, + .size = 0 + } +}; + +REGISTER_PLUGIN(&p) + +/** @} */ \ No newline at end of file diff --git a/lib/kernel/if.c b/lib/kernel/if.c index a9ccc4f5b..785596739 100644 --- a/lib/kernel/if.c +++ b/lib/kernel/if.c @@ -1,18 +1,15 @@ /** Interface related functions. * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include #include -#include #include -#include #include #include -#include #include "kernel/if.h" #include "kernel/tc.h" @@ -23,13 +20,11 @@ #include "utils.h" -struct interface * if_create(struct rtnl_link *link) +int if_init(struct interface *i, struct rtnl_link *link) { - struct interface *i = alloc(sizeof(struct interface)); - i->nl_link = link; - debug(DBG_SOCKET | 3, "Created interface '%s'", rtnl_link_get_name(i->nl_link)); + debug(LOG_IF | 3, "Created interface '%s'", rtnl_link_get_name(i->nl_link)); int n = if_get_irqs(i); if (n > 0) @@ -39,10 +34,10 @@ struct interface * if_create(struct rtnl_link *link) list_init(&i->sockets); - return i; + return 0; } -void if_destroy(struct interface *i) +int if_destroy(struct interface *i) { /* List members are freed by the nodes they belong to. */ list_destroy(&i->sockets, NULL, false); @@ -50,6 +45,8 @@ void if_destroy(struct interface *i) rtnl_qdisc_put(i->tc_qdisc); free(i); + + return 0; } int if_start(struct interface *i, int affinity) @@ -62,7 +59,9 @@ int if_start(struct interface *i, int affinity) /* Assign fwmark's to socket nodes which have netem options */ int ret, mark = 0; - list_foreach(struct socket *s, &i->sockets) { + for (size_t j = 0; j < list_length(&i->sockets); j++) { + struct socket *s = list_at(&i->sockets, j); + if (s->tc_qdisc) s->mark = 1 + mark++; } @@ -85,14 +84,16 @@ int if_start(struct interface *i, int affinity) error("Failed to setup priority queuing discipline: %s", nl_geterror(ret)); /* Create netem qdisks and appropriate filter per netem node */ - list_foreach(struct socket *s, &i->sockets) { + for (size_t j = 0; j < list_length(&i->sockets); j++) { + struct socket *s = list_at(&i->sockets, j); + if (s->tc_qdisc) { ret = tc_mark(i, &s->tc_classifier, TC_HANDLE(1, s->mark), s->mark); if (ret) error("Failed to setup FW mark classifier: %s", nl_geterror(ret)); char *buf = tc_print(s->tc_qdisc); - debug(DBG_SOCKET | 5, "Starting network emulation on interface '%s' for FW mark %u: %s", + debug(LOG_IF | 5, "Starting network emulation on interface '%s' for FW mark %u: %s", rtnl_link_get_name(i->nl_link), s->mark, buf); free(buf); @@ -193,7 +194,7 @@ int if_set_affinity(struct interface *i, int affinity) error("Failed to set affinity for IRQ %u", i->irqs[n]); fclose(file); - debug(DBG_SOCKET | 5, "Set affinity of IRQ %u for interface '%s' to %#x", i->irqs[n], rtnl_link_get_name(i->nl_link), affinity); + debug(LOG_IF | 5, "Set affinity of IRQ %u for interface '%s' to %#x", i->irqs[n], rtnl_link_get_name(i->nl_link), affinity); } else error("Failed to set affinity for interface '%s'", rtnl_link_get_name(i->nl_link)); diff --git a/lib/kernel/kernel.c b/lib/kernel/kernel.c index fd39c303b..9ce6131c8 100644 --- a/lib/kernel/kernel.c +++ b/lib/kernel/kernel.c @@ -1,7 +1,7 @@ /** Linux kernel related functions. * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include @@ -102,11 +102,6 @@ int kernel_has_version(int maj, int min) return version_cmp(¤t, &required) < 0; } -int kernel_is_rt() -{ - return access(SYSFS_PATH "/kernel/realtime", R_OK); -} - int kernel_get_cmdline_param(const char *param, char *buf, size_t len) { int ret; @@ -150,6 +145,38 @@ int kernel_get_cacheline_size() return sysconf(_SC_LEVEL1_ICACHE_LINESIZE); } +int kernel_get_nr_hugepages() +{ + FILE *f; + int nr, ret; + + f = fopen(PROCFS_PATH "/sys/vm/nr_hugepages", "r"); + if (!f) + serror("Failed to open %s", PROCFS_PATH "/sys/vm/nr_hugepages"); + + ret = fscanf(f, "%d", &nr); + if (ret != 1) + nr = -1; + + fclose(f); + + return nr; +} + +int kernel_set_nr_hugepages(int nr) +{ + FILE *f; + + f = fopen(PROCFS_PATH "/sys/vm/nr_hugepages", "w"); + if (!f) + serror("Failed to open %s", PROCFS_PATH "/sys/vm/nr_hugepages"); + + fprintf(f, "%d\n", nr); + fclose(f); + + return 0; +} + #if 0 int kernel_check_cap(cap_value_t cap) { diff --git a/lib/kernel/nl.c b/lib/kernel/nl.c index 16c2810d2..4eace3d6d 100644 --- a/lib/kernel/nl.c +++ b/lib/kernel/nl.c @@ -3,7 +3,7 @@ * VILLASnode uses libnl3 to talk to the Linux kernel to gather networking related information * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include diff --git a/lib/kernel/pci.c b/lib/kernel/pci.c index 0416f8488..177e5bb7a 100644 --- a/lib/kernel/pci.c +++ b/lib/kernel/pci.c @@ -1,15 +1,16 @@ /** Linux PCI helpers * * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel **********************************************************************************/ #include -#include #include #include +#include #include "log.h" +#include "utils.h" #include "kernel/pci.h" #include "config.h" @@ -31,7 +32,7 @@ int pci_init(struct pci *p) } while ((entry = readdir(dp))) { - struct pci_dev d; + struct pci_device d; struct { const char *s; int *p; } map[] = { { "vendor", &d.id.vendor }, @@ -57,6 +58,8 @@ int pci_init(struct pci *p) ret = sscanf(entry->d_name, "%4x:%2x:%2x.%u", &d.slot.domain, &d.slot.bus, &d.slot.device, &d.slot.function); if (ret != 4) error("Failed to parse PCI slot number: %s", entry->d_name); + + list_push(&p->devices, memdup(&d, sizeof(d))); } closedir(dp); @@ -64,22 +67,14 @@ int pci_init(struct pci *p) return 0; } -void pci_destroy(struct pci *p) +int pci_destroy(struct pci *p) { list_destroy(&p->devices, NULL, true); -} - -int pci_dev_init(struct pci_dev *d) -{ + return 0; } -void pci_dev_destroy(struct pci_dev *d) -{ - -} - -int pci_dev_parse_slot(struct pci_dev *f, const char *s, const char **error) +int pci_device_parse_slot(struct pci_device *f, const char *s, const char **error) { char *str = strdup(s); char *colon = strrchr(str, ':'); @@ -154,7 +149,7 @@ fail: } /* ID filter syntax: [vendor]:[device][:class] */ -int pci_dev_parse_id(struct pci_dev *f, const char *str, const char **error) +int pci_device_parse_id(struct pci_device *f, const char *str, const char **error) { char *s, *c, *e; @@ -210,7 +205,7 @@ fail: return -1; } -int pci_dev_compare(const struct pci_dev *d, const struct pci_dev *f) +int pci_device_compare(const struct pci_device *d, const struct pci_device *f) { if ((f->slot.domain >= 0 && f->slot.domain != d->slot.domain) || (f->slot.bus >= 0 && f->slot.bus != d->slot.bus) || @@ -231,12 +226,12 @@ int pci_dev_compare(const struct pci_dev *d, const struct pci_dev *f) return 1; } -struct pci_dev * pci_lookup_device(struct pci *p, struct pci_dev *f) +struct pci_device * pci_lookup_device(struct pci *p, struct pci_device *f) { - return list_search(&p->devices, (cmp_cb_t) pci_dev_compare, (void *) f); + return list_search(&p->devices, (cmp_cb_t) pci_device_compare, (void *) f); } -int pci_attach_driver(struct pci_dev *d, const char *driver) +int pci_attach_driver(struct pci_device *d, const char *driver) { FILE *f; char fn[256]; @@ -264,7 +259,7 @@ int pci_attach_driver(struct pci_dev *d, const char *driver) return 0; } -int pci_get_iommu_group(struct pci_dev *d) +int pci_get_iommu_group(struct pci_device *d) { int ret; char *group, link[1024], sysfs[1024]; diff --git a/lib/kernel/rt.c b/lib/kernel/rt.c index 4d904efad..f0507d03f 100644 --- a/lib/kernel/rt.c +++ b/lib/kernel/rt.c @@ -1,76 +1,108 @@ /** Linux specific real-time optimizations * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include +#include +#include "config.h" #include "utils.h" +#include "super_node.h" + #include "kernel/kernel.h" #include "kernel/rt.h" -int rt_init(int affinity, int priority) -{ INDENT - char isolcpus[255]; - int is_isol, is_rt, ret; +int rt_init(int priority, int affinity) +{ + info("Initialize real-time sub-system"); + + { INDENT + + int is_rt; /* Use FIFO scheduler with real time priority */ - is_rt = kernel_is_rt(); + is_rt = rt_is_preemptible(); if (is_rt) warn("We recommend to use an PREEMPT_RT patched kernel!"); + if (priority) + rt_set_priority(priority); + else + warn("You might want to use the 'priority' setting to increase VILLASnode's process priority"); + + if (affinity) + rt_set_affinity(affinity); + else + warn("You should use the 'affinity' setting to pin VILLASnode to dedicate CPU cores"); + + } + + return 0; +} + +int rt_set_affinity(int affinity) +{ + char isolcpus[255]; + int is_isol, ret; + + /* Pin threads to CPUs by setting the affinity */ + cpu_set_t cset_pin, cset_isol, cset_non_isol; + + cpuset_from_integer(affinity, &cset_pin); + + is_isol = kernel_get_cmdline_param("isolcpus", isolcpus, sizeof(isolcpus)); + if (is_isol) { + warn("You should reserve some cores for VILLASnode (see 'isolcpus')"); + + CPU_ZERO(&cset_isol); + } + else { + ret = cpulist_parse(isolcpus, &cset_isol, 0); + if (ret) + error("Invalid isolcpus cmdline parameter: %s", isolcpus); + + CPU_XOR(&cset_non_isol, &cset_isol, &cset_pin); + if (CPU_COUNT(&cset_non_isol) > 0) { + char isol[128], pin[128]; + + cpulist_create(isol, sizeof(isol), &cset_isol); + cpulist_create(pin, sizeof(pin), &cset_pin); + + warn("Affinity setting includes cores which are not isolated: affinity=%s isolcpus=%s", pin, isol); + } + } + + char list[128]; + cpulist_create(list, sizeof(list), &cset_pin); + + ret = sched_setaffinity(0, sizeof(cpu_set_t), &cset_pin); + if (ret) + serror("Failed to set CPU affinity to %s", list); + + debug(LOG_KERNEL | 3, "Set affinity to %s", list); + + return 0; +} + +int rt_set_priority(int priority) +{ + int ret; struct sched_param param = { .sched_priority = priority }; - if (priority) { - ret = sched_setscheduler(0, SCHED_FIFO, ¶m); - if (ret) - serror("Failed to set real time priority"); - - debug(3, "Task priority set to %u", priority); - } - - if (affinity) { - /* Pin threads to CPUs by setting the affinity */ - cpu_set_t cset_pin, cset_isol, cset_non_isol; - - cpuset_from_integer(affinity, &cset_pin); - - is_isol = kernel_get_cmdline_param("isolcpus", isolcpus, sizeof(isolcpus)); - if (is_isol) { - warn("You should reserve some cores for VILLASnode (see 'isolcpus')"); - - CPU_ZERO(&cset_isol); - } - else { - ret = cpulist_parse(isolcpus, &cset_isol, 0); - if (ret) - error("Invalid isolcpus cmdline parameter: %s", isolcpus); - - CPU_XOR(&cset_non_isol, &cset_isol, &cset_pin); - if (CPU_COUNT(&cset_non_isol) > 0) { - char isol[128], pin[128]; - - cpulist_create(isol, sizeof(isol), &cset_isol); - cpulist_create(pin, sizeof(pin), &cset_pin); - - warn("Affinity setting includes cores which are not isolated: affinity=%s isolcpus=%s", pin, isol); - } - } - - char list[128]; - cpulist_create(list, sizeof(list), &cset_pin); - - ret = sched_setaffinity(0, sizeof(cpu_set_t), &cset_pin); - if (ret) - serror("Failed to set CPU affinity to %s", list); - - debug(3, "Set affinity to %s", list); - } - else - warn("You should use the 'affinity' setting to pin VILLASnode to dedicate CPU cores"); + ret = sched_setscheduler(0, SCHED_FIFO, ¶m); + if (ret) + serror("Failed to set real time priority"); + debug(LOG_KERNEL | 3, "Task priority set to %u", priority); + return 0; +} + +int rt_is_preemptible() +{ + return access(SYSFS_PATH "/kernel/realtime", R_OK); } \ No newline at end of file diff --git a/lib/kernel/tc.c b/lib/kernel/tc.c index 946f88aa2..bf0b52348 100644 --- a/lib/kernel/tc.c +++ b/lib/kernel/tc.c @@ -3,7 +3,7 @@ * VILLASnode uses these functions to setup the network emulation feature. * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include @@ -134,6 +134,7 @@ char * tc_print(struct rtnl_qdisc *ne) int tc_prio(struct interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hdl_t parent, int bands) { + int ret; struct nl_sock *sock = nl_init(); struct rtnl_qdisc *q = rtnl_qdisc_alloc(); @@ -151,10 +152,12 @@ int tc_prio(struct interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hdl rtnl_qdisc_prio_set_bands(q, bands + 3); rtnl_qdisc_prio_set_priomap(q, map, sizeof(map)); - int ret = rtnl_qdisc_add(sock, q, NLM_F_CREATE | NLM_F_REPLACE); + ret = rtnl_qdisc_add(sock, q, NLM_F_CREATE | NLM_F_REPLACE); *qd = q; + debug(LOG_TC | 3, "Added prio qdisc with %d bands to interface '%s'", bands, rtnl_link_get_name(i->nl_link)); + return ret; } @@ -172,6 +175,8 @@ int tc_netem(struct interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hd *qd = q; + debug(LOG_TC | 3, "Added netem qdisc to interface '%s'", rtnl_link_get_name(i->nl_link)); + return ret; } @@ -193,6 +198,8 @@ int tc_mark(struct interface *i, struct rtnl_cls **cls, tc_hdl_t flowid, uint32_ *cls = c; + debug(LOG_TC | 3, "Added fwmark classifier with mark %d to interface '%s'", mark, rtnl_link_get_name(i->nl_link)); + return ret; } diff --git a/lib/kernel/vfio.c b/lib/kernel/vfio.c index 72573a657..2e8c4e730 100644 --- a/lib/kernel/vfio.c +++ b/lib/kernel/vfio.c @@ -1,7 +1,7 @@ /** Virtual Function IO wrapper around kernel API * * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel **********************************************************************************/ #define _DEFAULT_SOURCE @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -25,8 +24,6 @@ #include "kernel/vfio.h" #include "kernel/pci.h" -#include "fpga/dma.h" - static const char *vfio_pci_region_names[] = { "PCI_BAR0", // VFIO_PCI_BAR0_REGION_INDEX, "PCI_BAR1", // VFIO_PCI_BAR1_REGION_INDEX, @@ -89,26 +86,28 @@ int vfio_destroy(struct vfio_container *v) return 0; } -void vfio_group_destroy(struct vfio_group *g) +int vfio_group_destroy(struct vfio_group *g) { int ret; - list_destroy(&g->devices, (dtor_cb_t) vfio_dev_destroy, false); + list_destroy(&g->devices, (dtor_cb_t) vfio_device_destroy, false); ret = ioctl(g->fd, VFIO_GROUP_UNSET_CONTAINER); if (ret) - return; + return ret; debug(5, "VFIO: released group from container: group=%u", g->index); ret = close(g->fd); if (ret) - return; + return ret; debug(5, "VFIO: closed group: group=%u, fd=%d", g->index, g->fd); + + return 0; } -void vfio_dev_destroy(struct vfio_dev *d) +int vfio_device_destroy(struct vfio_device *d) { int ret; @@ -117,12 +116,14 @@ void vfio_dev_destroy(struct vfio_dev *d) ret = close(d->fd); if (ret) - return; + return ret; debug(5, "VFIO: closed device: name=%s, fd=%d", d->name, d->fd); free(d->mappings); free(d->name); + + return 0; } /* Constructors */ @@ -203,7 +204,7 @@ int vfio_group_attach(struct vfio_group *g, struct vfio_container *c, int index) return 0; } -int vfio_pci_attach(struct vfio_dev *d, struct vfio_container *c, struct pci_dev *pdev) +int vfio_pci_attach(struct vfio_device *d, struct vfio_container *c, struct pci_device *pdev) { char name[32]; int ret; @@ -225,28 +226,30 @@ int vfio_pci_attach(struct vfio_dev *d, struct vfio_container *c, struct pci_dev /* VFIO device name consists of PCI BDF */ snprintf(name, sizeof(name), "%04x:%02x:%02x.%x", pdev->slot.domain, pdev->slot.bus, pdev->slot.device, pdev->slot.function); - ret = vfio_dev_attach(d, c, name, index); + ret = vfio_device_attach(d, c, name, index); if (ret < 0) return ret; /* Check if this is really a vfio-pci device */ if (!(d->info.flags & VFIO_DEVICE_FLAGS_PCI)) { - vfio_dev_destroy(d); + vfio_device_destroy(d); return -1; } - d->pdev = pdev; + d->pci_device = pdev; return 0; } -int vfio_dev_attach(struct vfio_dev *d, struct vfio_container *c, const char *name, int index) +int vfio_device_attach(struct vfio_device *d, struct vfio_container *c, const char *name, int index) { int ret; struct vfio_group *g = NULL; /* Check if group already exists */ - list_foreach(struct vfio_group *h, &c->groups) { + for (size_t i = 0; i < list_length(&c->groups); i++) { + struct vfio_group *h = list_at(&c->groups, i); + if (h->index == index) g = h; } @@ -310,7 +313,7 @@ int vfio_dev_attach(struct vfio_dev *d, struct vfio_container *c, const char *na return 0; } -int vfio_pci_reset(struct vfio_dev *d) +int vfio_pci_reset(struct vfio_device *d) { int ret; @@ -350,7 +353,7 @@ int vfio_pci_reset(struct vfio_dev *d) return ret; } -int vfio_pci_msi_find(struct vfio_dev *d, int nos[32]) +int vfio_pci_msi_find(struct vfio_device *d, int nos[32]) { int ret, idx, irq; char *end, *col, *last, line[1024], name[13]; @@ -390,7 +393,7 @@ int vfio_pci_msi_find(struct vfio_dev *d, int nos[32]) return 0; } -int vfio_pci_msi_deinit(struct vfio_dev *d, int efds[32]) +int vfio_pci_msi_deinit(struct vfio_device *d, int efds[32]) { int ret, irq_setlen, irq_count = d->irqs[VFIO_PCI_MSI_IRQ_INDEX].count; struct vfio_irq_set *irq_set; @@ -424,7 +427,7 @@ int vfio_pci_msi_deinit(struct vfio_dev *d, int efds[32]) return irq_count; } -int vfio_pci_msi_init(struct vfio_dev *d, int efds[32]) +int vfio_pci_msi_init(struct vfio_device *d, int efds[32]) { int ret, irq_setlen, irq_count = d->irqs[VFIO_PCI_MSI_IRQ_INDEX].count; struct vfio_irq_set *irq_set; @@ -459,7 +462,7 @@ int vfio_pci_msi_init(struct vfio_dev *d, int efds[32]) return irq_count; } -int vfio_pci_enable(struct vfio_dev *d) +int vfio_pci_enable(struct vfio_device *d) { int ret; uint32_t reg; @@ -483,7 +486,7 @@ int vfio_pci_enable(struct vfio_dev *d) return 0; } -int vfio_dev_reset(struct vfio_dev *d) +int vfio_device_reset(struct vfio_device *d) { if (d->info.flags & VFIO_DEVICE_FLAGS_RESET) return ioctl(d->fd, VFIO_DEVICE_RESET); @@ -496,13 +499,18 @@ void vfio_dump(struct vfio_container *v) info("VFIO Version: %u", v->version); info("VFIO Extensions: %#x", v->extensions); - list_foreach(struct vfio_group *g, &v->groups) { + for (size_t i = 0; i < list_length(&v->groups); i++) { + struct vfio_group *g = list_at(&v->groups, i); + info("VFIO Group %u, viable=%u, container=%d", g->index, (g->status.flags & VFIO_GROUP_FLAGS_VIABLE) > 0, (g->status.flags & VFIO_GROUP_FLAGS_CONTAINER_SET) > 0 ); - list_foreach(struct vfio_dev *d, &g->devices) { INDENT + + for (size_t i = 0; i < list_length(&g->devices); i++) { INDENT + struct vfio_device *d = list_at(&g->devices, i); + info("Device %s: regions=%u, irqs=%u, flags=%#x", d->name, d->info.num_regions, d->info.num_irqs, @@ -535,7 +543,7 @@ void vfio_dump(struct vfio_container *v) } } -void * vfio_map_region(struct vfio_dev *d, int idx) +void * vfio_map_region(struct vfio_device *d, int idx) { struct vfio_region_info *r = &d->regions[idx]; @@ -547,7 +555,7 @@ void * vfio_map_region(struct vfio_dev *d, int idx) return d->mappings[idx]; } -int vfio_unmap_region(struct vfio_dev *d, int idx) +int vfio_unmap_region(struct vfio_device *d, int idx) { int ret; struct vfio_region_info *r = &d->regions[idx]; @@ -566,25 +574,26 @@ int vfio_unmap_region(struct vfio_dev *d, int idx) return 0; } -int vfio_map_dma(struct vfio_container *c, struct dma_mem *mem) +int vfio_map_dma(struct vfio_container *c, uint64_t virt, uint64_t phys, size_t len) { int ret; - if (mem->len & 0xFFF) { - mem->len += 0x1000; - mem->len &= ~0xFFF; + if (len & 0xFFF) { + len += 0x1000; + len &= ~0xFFF; } - if (mem->base_phys == (void *) -1) { - mem->base_phys = c->iova_next; - c->iova_next += mem->len; + /* Super stupid allocator */ + if (phys == -1) { + phys = c->iova_next; + c->iova_next += len; } struct vfio_iommu_type1_dma_map dma_map = { .argsz = sizeof(struct vfio_iommu_type1_dma_map), - .vaddr = (uint64_t) mem->base_virt, - .iova = (uint64_t) mem->base_phys, - .size = mem->len, + .vaddr = virt, + .iova = phys, + .size = len, .flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE }; @@ -597,15 +606,15 @@ int vfio_map_dma(struct vfio_container *c, struct dma_mem *mem) return 0; } -int vfio_unmap_dma(struct vfio_container *c, struct dma_mem *mem) +int vfio_unmap_dma(struct vfio_container *c, uint64_t virt, uint64_t phys, size_t len) { int ret; struct vfio_iommu_type1_dma_unmap dma_unmap = { .argsz = sizeof(struct vfio_iommu_type1_dma_unmap), .flags = 0, - .iova = (uint64_t) mem->base_phys, - .size = mem->len, + .iova = phys, + .size = len, }; ret = ioctl(c->fd, VFIO_IOMMU_UNMAP_DMA, &dma_unmap); diff --git a/lib/list.c b/lib/list.c index e395e5546..2dfd2b416 100644 --- a/lib/list.c +++ b/lib/list.c @@ -3,13 +3,14 @@ * Linked lists a used for several data structures in the code. * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include #include #include "list.h" +#include "utils.h" /* Compare functions */ static int cmp_lookup(const void *a, const void *b) { @@ -32,19 +33,26 @@ static int cmp_sort(const void *a, const void *b, void *thunk) { void list_init(struct list *l) { + assert(l->state == STATE_DESTROYED); + pthread_mutex_init(&l->lock, NULL); l->length = 0; l->capacity = 0; - l->array = NULL; + + l->state = STATE_INITIALIZED; } -void list_destroy(struct list *l, dtor_cb_t destructor, bool release) +int list_destroy(struct list *l, dtor_cb_t destructor, bool release) { pthread_mutex_lock(&l->lock); - list_foreach(void *p, l) { + assert(l->state != STATE_DESTROYED); + + for (size_t i = 0; i < list_length(l); i++) { + void *p = list_at(l, i); + if (destructor) destructor(p); if (release) @@ -60,11 +68,17 @@ void list_destroy(struct list *l, dtor_cb_t destructor, bool release) pthread_mutex_unlock(&l->lock); pthread_mutex_destroy(&l->lock); + + l->state = STATE_DESTROYED; + + return 0; } void list_push(struct list *l, void *p) { pthread_mutex_lock(&l->lock); + + assert(l->state == STATE_INITIALIZED); /* Resize array if out of capacity */ if (l->length >= l->capacity) { @@ -84,7 +98,9 @@ void list_remove(struct list *l, void *p) pthread_mutex_lock(&l->lock); - for (int i = 0; i < l->length; i++) { + assert(l->state == STATE_INITIALIZED); + + for (size_t i = 0; i < list_length(l); i++) { if (l->array[i] == p) removed++; else @@ -112,7 +128,11 @@ int list_count(struct list *l, cmp_cb_t cmp, void *ctx) pthread_mutex_lock(&l->lock); - list_foreach(void *e, l) { + assert(l->state == STATE_INITIALIZED); + + for (size_t i = 0; i < list_length(l); i++) { + void *e = list_at(l, i); + if (cmp(e, ctx) == 0) c++; } @@ -127,9 +147,12 @@ void * list_search(struct list *l, cmp_cb_t cmp, void *ctx) void *e; pthread_mutex_lock(&l->lock); + + assert(l->state == STATE_INITIALIZED); - list_foreach(e, l) { - if (!cmp(e, ctx)) + for (size_t i = 0; i < list_length(l); i++) { + e = list_at(l, i); + if (cmp(e, ctx) == 0) goto out; } @@ -144,6 +167,8 @@ void list_sort(struct list *l, cmp_cb_t cmp) { pthread_mutex_lock(&l->lock); + assert(l->state == STATE_INITIALIZED); + qsort_r(l->array, l->length, sizeof(void *), cmp_sort, (void *) cmp); pthread_mutex_unlock(&l->lock); diff --git a/lib/log.c b/lib/log.c index d2b12682e..7c670447b 100644 --- a/lib/log.c +++ b/lib/log.c @@ -1,10 +1,11 @@ /** Logging and debugging routines * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include +#include #include #include #include @@ -21,21 +22,109 @@ #include "OpalPrint.h" #endif -/** Debug level used by the debug() macro. - * It defaults to V (defined by the Makefile) and can be - * overwritten by the 'debug' setting in the configuration file. */ -static unsigned level = V; +/** The global log instance. */ +static struct log *log; -/** Debug facilities used by the debug() macro. */ -static unsigned facilities = ~0; - -/** A global clock used to prefix the log messages. */ -static struct timespec epoch; +/** List of debug facilities as strings */ +static const char *facilities_strs[] = { + "pool", /* LOG_POOL */ + "queue", /* LOG_QUEUE */ + "config", /* LOG_CONFIG */ + "hook", /* LOG_HOOK */ + "path", /* LOG_PATH */ + "node", /* LOG_NODE */ + "mem", /* LOG_MEM */ + "web", /* LOG_WEB */ + "api", /* LOG_API */ + "log", /* LOG_LOG */ + "vfio", /* LOG_VFIO */ + "pci", /* LOG_PCI */ + "xil", /* LOG_XIL */ + "tc", /* LOG_TC */ + "if", /* LOG_IF */ + + /* Node-types */ + "socket", /* LOG_SOCKET */ + "file", /* LOG_FILE */ + "fpga", /* LOG_FPGA */ + "ngsi", /* LOG_NGSI */ + "websocket", /* LOG_WEBSOCKET */ + "opal", /* LOG_OPAL */ +}; #ifdef __GNUC__ /** The current log indention level (per thread!). */ static __thread int indent = 0; +int log_init(struct log *l, int level, long facilitites) +{ + /* Register this log instance globally */ + log = l; + + l->level = level; + l->facilities = facilitites; + + debug(LOG_LOG | 5, "Log sub-system intialized: level=%d, faciltities=%#lx", level, facilitites); + + l->state = STATE_INITIALIZED; + + return 0; +} + +int log_parse(struct log *l, config_setting_t *cfg) +{ + const char *facilities; + + if (!config_setting_is_group(cfg)) + cerror(cfg, "Setting 'log' must be a group."); + + config_setting_lookup_int(cfg, "level", &l->level); + config_setting_lookup_string(cfg, "file", &l->path); + + if (config_setting_lookup_string(cfg, "facilities", &facilities)) + log_set_facility_expression(l, facilities); + + l->state = STATE_PARSED; + + return 0; +} + +int log_start(struct log *l) +{ + l->epoch = time_now(); + + l->file = l->path ? fopen(l->path, "a+") : stderr; + if (!l->file) { + l->file = stderr; + error("Failed to open log file '%s'", l->path); + } + + l->state = STATE_STARTED; + + return 0; +} + +int log_stop(struct log *l) +{ + assert(l->state == STATE_STARTED); + + if (l->file != stderr && l->file != stdout) + fclose(l->file); + + l->state = STATE_STOPPED; + + return 0; +} + +int log_destroy(struct log *l) +{ + assert(l->state != STATE_STARTED); + + l->state = STATE_DESTROYED; + + return 0; +} + int log_indent(int levels) { int old = indent; @@ -49,34 +138,72 @@ void log_outdent(int *old) } #endif -void log_setlevel(int lvl, int fac) +int log_set_facility_expression(struct log *l, const char *expression) { - level = lvl; - debug(10, "Switched to debug level %u", level); + bool negate; + char *copy, *token; + long mask = 0, facilities = 0; + + copy = strdup(expression); + token = strtok(copy, ","); + + while (token != NULL) { + if (token[0] == '!') { + token++; + negate = true; + } + else + negate = false; + + /* Check for some classes */ + if (!strcmp(token, "all")) + mask = LOG_ALL; + else if (!strcmp(token, "nodes")) + mask = LOG_NODES; + else if (!strcmp(token, "kernel")) + mask = LOG_KERNEL; + else { + for (int ind = 0; ind < ARRAY_LEN(facilities_strs); ind++) { + if (!strcmp(token, facilities_strs[ind])) { + mask = (1 << (ind+8)); + goto found; + } + } + + error("Invalid log class '%s'", token); + } + +found: if (negate) + facilities &= ~mask; + else + facilities |= mask; + + token = strtok(NULL, ","); + } + + l->facilities = facilities; + + free(copy); + + return l->facilities; } -void log_init() -{ - epoch = time_now(); - debug(10, "Debug clock resetted"); -} - -void log_print(const char *lvl, const char *fmt, ...) +void log_print(struct log *l, const char *lvl, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - log_vprint(lvl, fmt, ap); + log_vprint(l, lvl, fmt, ap); va_end(ap); } -void log_vprint(const char *lvl, const char *fmt, va_list ap) +void log_vprint(struct log *l, const char *lvl, const char *fmt, va_list ap) { struct timespec ts = time_now(); char *buf = alloc(512); /* Timestamp */ - strcatf(&buf, "%10.3f ", time_delta(&epoch, &ts)); + strcatf(&buf, "%10.3f ", time_delta(&l->epoch, &ts)); /* Severity */ strcatf(&buf, "%5s ", lvl); @@ -96,7 +223,7 @@ void log_vprint(const char *lvl, const char *fmt, va_list ap) #ifdef ENABLE_OPAL_ASYNC OpalPrint("VILLASnode: %s\n", buf); #endif - fprintf(stderr, "\r%s\n", buf); + fprintf(l->file, "\r%s\n", buf); free(buf); } @@ -105,19 +232,21 @@ void line() char buf[LOG_WIDTH]; memset(buf, 0x71, sizeof(buf)); - log_print("", "\b" ACS("%.*s"), LOG_WIDTH, buf); + log_print(log, "", "\b" ACS("%.*s"), LOG_WIDTH, buf); } -void debug(int class, const char *fmt, ...) +void debug(long class, const char *fmt, ...) { va_list ap; int lvl = class & 0xFF; int fac = class & ~0xFF; + + assert(log != NULL); - if (((fac == 0) || (fac & facilities)) && (lvl <= level)) { + if (((fac == 0) || (fac & log->facilities)) && (lvl <= log->level)) { va_start(ap, fmt); - log_vprint(LOG_LVL_DEBUG, fmt, ap); + log_vprint(log, LOG_LVL_DEBUG, fmt, ap); va_end(ap); } } @@ -125,18 +254,22 @@ void debug(int class, const char *fmt, ...) void info(const char *fmt, ...) { va_list ap; + + assert(log != NULL); va_start(ap, fmt); - log_vprint(LOG_LVL_INFO, fmt, ap); + log_vprint(log, LOG_LVL_INFO, fmt, ap); va_end(ap); } void warn(const char *fmt, ...) { va_list ap; + + assert(log != NULL); va_start(ap, fmt); - log_vprint(LOG_LVL_WARN, fmt, ap); + log_vprint(log, LOG_LVL_WARN, fmt, ap); va_end(ap); } @@ -144,17 +277,21 @@ void stats(const char *fmt, ...) { va_list ap; + assert(log != NULL); + va_start(ap, fmt); - log_vprint(LOG_LVL_STATS, fmt, ap); + log_vprint(log, LOG_LVL_STATS, fmt, ap); va_end(ap); } void error(const char *fmt, ...) { va_list ap; + + assert(log != NULL); va_start(ap, fmt); - log_vprint(LOG_LVL_ERROR, fmt, ap); + log_vprint(log, LOG_LVL_ERROR, fmt, ap); va_end(ap); die(); @@ -165,11 +302,13 @@ void serror(const char *fmt, ...) va_list ap; char *buf = NULL; + assert(log != NULL); + va_start(ap, fmt); vstrcatf(&buf, fmt, ap); va_end(ap); - log_print(LOG_LVL_ERROR, "%s: %m (%u)", buf, errno); + log_print(log, LOG_LVL_ERROR, "%s: %m (%u)", buf, errno); free(buf); die(); @@ -179,16 +318,21 @@ void cerror(config_setting_t *cfg, const char *fmt, ...) { va_list ap; char *buf = NULL; + const char *file; + int line; + + assert(log != NULL); va_start(ap, fmt); vstrcatf(&buf, fmt, ap); va_end(ap); + + line = config_setting_source_line(cfg); + file = config_setting_source_file(cfg); + if (!file) + file = config_setting_get_hook(config_root_setting(cfg->config)); - log_print(LOG_LVL_ERROR, "%s in %s:%u", buf, - config_setting_source_file(cfg) - ? config_setting_source_file(cfg) - : "(stdio)", - config_setting_source_line(cfg)); + log_print(log, LOG_LVL_ERROR, "%s in %s:%u", buf, file, line); free(buf); die(); diff --git a/lib/mapping.c b/lib/mapping.c new file mode 100644 index 000000000..14caac235 --- /dev/null +++ b/lib/mapping.c @@ -0,0 +1,320 @@ +/** Sample value remapping for mux. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#include + +#include "mapping.h" +#include "stats.h" +#include "sample.h" +#include "list.h" +#include "utils.h" + +int mapping_entry_parse_str(struct mapping_entry *e, const char *str) +{ + char *cpy, *type, *field, *subfield, *end; + + cpy = strdup(str); + if (!cpy) + return -1; + + type = strtok(cpy, ".["); + if (!type) + goto invalid_format; + + if (!strcmp(type, "stats")) { + e->type = MAPPING_TYPE_STATS; + e->length = 1; + + field = strtok(NULL, "."); + if (!field) + goto invalid_format; + + subfield = strtok(NULL, "."); + if (!subfield) + goto invalid_format; + + end = strtok(NULL, "."); + if (end) + goto invalid_format; + + e->stats.id = stats_lookup_id(field); + if (e->stats.id < 0) + goto invalid_format; + + if (!strcmp(subfield, "total")) + e->stats.type = MAPPING_STATS_TYPE_TOTAL; + else if (!strcmp(subfield, "last")) + e->stats.type = MAPPING_STATS_TYPE_LAST; + else if (!strcmp(subfield, "lowest")) + e->stats.type = MAPPING_STATS_TYPE_LOWEST; + else if (!strcmp(subfield, "highest")) + e->stats.type = MAPPING_STATS_TYPE_HIGHEST; + else if (!strcmp(subfield, "mean")) + e->stats.type = MAPPING_STATS_TYPE_MEAN; + else if (!strcmp(subfield, "var")) + e->stats.type = MAPPING_STATS_TYPE_VAR; + else if (!strcmp(subfield, "stddev")) + e->stats.type = MAPPING_STATS_TYPE_STDDEV; + else + goto invalid_format; + } + else if (!strcmp(type, "hdr")) { + e->type = MAPPING_TYPE_HEADER; + e->length = 1; + + field = strtok(NULL, "."); + if (!field) + goto invalid_format; + + end = strtok(NULL, "."); + if (end) + goto invalid_format; + + if (!strcmp(field, "sequence")) + e->header.id = MAPPING_HEADER_SEQUENCE; + else if (!strcmp(field, "length")) + e->header.id = MAPPING_HEADER_LENGTH; + else + goto invalid_format; + } + else if (!strcmp(type, "ts")) { + e->type = MAPPING_TYPE_TIMESTAMP; + e->length = 2; + + field = strtok(NULL, "."); + if (!field) + goto invalid_format; + + end = strtok(NULL, "."); + if (end) + goto invalid_format; + + if (!strcmp(field, "origin")) + e->timestamp.id = MAPPING_TIMESTAMP_ORIGIN; + else if (!strcmp(field, "received")) + e->timestamp.id = MAPPING_TIMESTAMP_RECEIVED; + else + goto invalid_format; + } + else if (!strcmp(type, "data")) { + char *first_str, *last_str, *endptr; + int first, last; + + e->type = MAPPING_TYPE_DATA; + + first_str = strtok(NULL, "-]"); + if (!first_str) + goto invalid_format; + + last_str = strtok(NULL, "]"); + if (!last_str) + last_str = first_str; /* single element: data[5] => data[5-5] */ + + end = strtok(NULL, "."); + if (end) + goto invalid_format; + + first = strtoul(first_str, &endptr, 10); + if (endptr != first_str + strlen(first_str)) + goto invalid_format; + + last = strtoul(last_str, &endptr, 10); + if (endptr != last_str + strlen(last_str)) + goto invalid_format; + + if (last < first) + goto invalid_format; + + e->data.offset = first; + e->length = last - first + 1; + } + else + goto invalid_format; + + free(cpy); + return 0; + +invalid_format: + + free(cpy); + return -1; +} + +int mapping_entry_parse(struct mapping_entry *e, config_setting_t *cfg) +{ + const char *str; + + str = config_setting_get_string(cfg); + if (!str) + return -1; + + return mapping_entry_parse_str(e, str); +} + +int mapping_init(struct mapping *m) +{ + assert(m->state == STATE_DESTROYED); + + list_init(&m->entries); + + m->state = STATE_INITIALIZED; + + return 0; +} + +int mapping_destroy(struct mapping *m) +{ + assert(m->state != STATE_DESTROYED); + + list_destroy(&m->entries, NULL, true); + + m->state = STATE_DESTROYED; + + return 0; +} + +int mapping_parse(struct mapping *m, config_setting_t *cfg) +{ + int ret; + + assert(m->state == STATE_INITIALIZED); + + if (!config_setting_is_array(cfg)) + return -1; + + m->real_length = 0; + + for (int i = 0; i < config_setting_length(cfg); i++) { + struct mapping_entry e; + config_setting_t *cfg_mapping; + + cfg_mapping = config_setting_get_elem(cfg, i); + if (!cfg_mapping) + return -1; + + ret = mapping_entry_parse(&e, cfg_mapping); + if (ret) + return ret; + + list_push(&m->entries, memdup(&e, sizeof(e))); + + m->real_length += e.length; + } + + m->state = STATE_PARSED; + + return 0; +} + +int mapping_remap(struct mapping *m, struct sample *original, struct sample *remapped, struct stats *s) +{ + int k = 0; + + if (remapped->capacity < m->real_length) + return -1; + + /* We copy all the header fields */ + remapped->sequence = original->sequence; + remapped->pool = original->pool; + remapped->source = original->source; + remapped->ts = original->ts; + remapped->format = 0; + remapped->length = 0; + + for (size_t i = 0; i < list_length(&m->entries); i++) { + struct mapping_entry *e = list_at(&m->entries, i); + + switch (e->type) { + case MAPPING_TYPE_STATS: { + struct hist *h = &s->histograms[e->stats.id]; + + switch (e->stats.type) { + case MAPPING_STATS_TYPE_TOTAL: + sample_set_data_format(remapped, k, SAMPLE_DATA_FORMAT_INT); + remapped->data[k++].f = h->total; + break; + case MAPPING_STATS_TYPE_LAST: + remapped->data[k++].f = h->last; + break; + case MAPPING_STATS_TYPE_HIGHEST: + remapped->data[k++].f = h->highest; + break; + case MAPPING_STATS_TYPE_LOWEST: + remapped->data[k++].f = h->lowest; + break; + case MAPPING_STATS_TYPE_MEAN: + remapped->data[k++].f = hist_mean(h); + break; + case MAPPING_STATS_TYPE_STDDEV: + remapped->data[k++].f = hist_stddev(h); + break; + case MAPPING_STATS_TYPE_VAR: + remapped->data[k++].f = hist_var(h); + break; + default: + return -1; + } + } + + case MAPPING_TYPE_TIMESTAMP: { + struct timespec *ts; + + switch (e->timestamp.id) { + case MAPPING_TIMESTAMP_RECEIVED: + ts = &original->ts.received; + break; + case MAPPING_TIMESTAMP_ORIGIN: + ts = &original->ts.origin; + break; + default: + return -1; + } + + sample_set_data_format(remapped, k, SAMPLE_DATA_FORMAT_INT); + sample_set_data_format(remapped, k+1, SAMPLE_DATA_FORMAT_INT); + + remapped->data[k++].i = ts->tv_sec; + remapped->data[k++].i = ts->tv_nsec; + + break; + } + + case MAPPING_TYPE_HEADER: + sample_set_data_format(remapped, k, SAMPLE_DATA_FORMAT_INT); + + switch (e->header.id) { + case MAPPING_HEADER_LENGTH: + remapped->data[k++].i = original->length; + break; + case MAPPING_HEADER_SEQUENCE: + remapped->data[k++].i = original->sequence; + break; + default: + return -1; + } + break; + + case MAPPING_TYPE_DATA: + for (int j = e->data.offset; j < e->length + e->data.offset; j++) { + int f = sample_get_data_format(original, j); + + if (j >= original->length) { + sample_set_data_format(remapped, k, SAMPLE_DATA_FORMAT_FLOAT); + remapped->data[k++].f = 0; + } + else { + sample_set_data_format(remapped, k, f); + remapped->data[k++] = original->data[j]; + } + } + break; + } + + remapped->length += e->length; + } + + return 0; +} \ No newline at end of file diff --git a/lib/memory.c b/lib/memory.c index c332b073d..ead4f6265 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -1,8 +1,8 @@ /** Memory allocators. * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC - */ + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ #include #include @@ -10,33 +10,64 @@ /* Required to allocate hugepages on Apple OS X */ #ifdef __MACH__ #include +#elif defined(__linux__) + #include "kernel/kernel.h" #endif #include "log.h" #include "memory.h" +#include "utils.h" + +int memory_init(int hugepages) +{ +#ifdef __linux__ + info("Initialize memory sub-system"); + + int nr = kernel_get_nr_hugepages(); + + if (nr < hugepages) { INDENT + kernel_set_nr_hugepages(hugepages); + debug(LOG_MEM | 2, "Reserved %d hugepages (was %d)", hugepages, nr); + } +#endif + return 0; +} void * memory_alloc(const struct memtype *m, size_t len) { - debug(DBG_MEM | 2, "Allocating %#zx bytes of %s memory", len, m->name); - return m->alloc(len); + void *ptr = m->alloc(len, sizeof(void *)); + + debug(LOG_MEM | 2, "Allocated %#zx bytes of %s memory: %p", len, m->name, ptr); + + return ptr; } void * memory_alloc_aligned(const struct memtype *m, size_t len, size_t alignment) { - debug(DBG_MEM | 2, "Allocating %#zx bytes of %#zx-byte-aligned %s memory", len, alignment, m->name); - warn("%s: not implemented yet!", __FUNCTION__); - return memory_alloc(m, len); + void *ptr = m->alloc(len, alignment); + + debug(LOG_MEM | 2, "Allocated %#zx bytes of %#zx-byte-aligned %s memory: %p", len, alignment, m->name, ptr); + + return ptr; } int memory_free(const struct memtype *m, void *ptr, size_t len) { - debug(DBG_MEM | 2, "Releasing %#zx bytes of %s memory", len, m->name); + debug(LOG_MEM | 2, "Releasing %#zx bytes of %s memory", len, m->name); return m->free(ptr, len); } -static void * memory_heap_alloc(size_t len) +static void * memory_heap_alloc(size_t len, size_t alignment) { - return malloc(len); + void *ptr; + int ret; + + if (alignment < sizeof(void *)) + alignment = sizeof(void *); + + ret = posix_memalign(&ptr, alignment, len); + + return ret ? NULL : ptr; } int memory_heap_free(void *ptr, size_t len) @@ -47,7 +78,7 @@ int memory_heap_free(void *ptr, size_t len) } /** Allocate memory backed by hugepages with malloc() like interface */ -static void * memory_hugepage_alloc(size_t len) +static void * memory_hugepage_alloc(size_t len, size_t alignment) { int prot = PROT_READ | PROT_WRITE; int flags = MAP_PRIVATE | MAP_ANONYMOUS; diff --git a/lib/msg.c b/lib/msg.c index 7b3c4e0e8..006fae1a6 100644 --- a/lib/msg.c +++ b/lib/msg.c @@ -1,13 +1,9 @@ /** Message related functions. * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ -#include -#include -#include - #ifdef __linux__ #include #elif defined(__PPC__) /* Xilinx toolchain */ diff --git a/lib/node.c b/lib/node.c index 894e91344..46396daaa 100644 --- a/lib/node.c +++ b/lib/node.c @@ -1,22 +1,134 @@ /** Nodes. * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include +#include #include "sample.h" #include "node.h" -#include "cfg.h" #include "utils.h" +#include "config.h" +#include "plugin.h" -/** List of registered node-types */ -struct list node_types = LIST_INIT(); +int node_init(struct node *n, struct node_type *vt) +{ + assert(n->state == STATE_DESTROYED); + + n->_vt = vt; + n->_vd = alloc(vt->size); + + /* Default values */ + n->vectorize = 1; + + list_push(&vt->instances, n); + + n->state = STATE_INITIALIZED; + + return 0; +} int node_parse(struct node *n, config_setting_t *cfg) { - return n->_vt->parse ? n->_vt->parse(n, cfg) : 0; + struct plugin *p; + const char *type, *name; + int ret; + + name = config_setting_name(cfg); + + if (!config_setting_lookup_string(cfg, "type", &type)) + cerror(cfg, "Missing node type"); + + p = plugin_lookup(PLUGIN_TYPE_NODE, type); + assert(&p->node == n->_vt); + + config_setting_lookup_int(cfg, "vectorize", &n->vectorize); + + n->name = name; + n->cfg = cfg; + + ret = n->_vt->parse ? n->_vt->parse(n, cfg) : 0; + if (ret) + cerror(cfg, "Failed to parse node '%s'", node_name(n)); + + n->state = STATE_PARSED; + + return ret; +} + +int node_check(struct node *n) +{ + assert(n->state != STATE_DESTROYED); + + if (n->vectorize <= 0) + error("Invalid `vectorize` value %d for node %s. Must be natural number!", n->vectorize, node_name(n)); + + if (n->_vt->vectorize && n->_vt->vectorize < n->vectorize) + error("Invalid value for `vectorize`. Node type requires a number smaller than %d!", + n->_vt->vectorize); + + n->state = STATE_CHECKED; + + return 0; +} + +int node_start(struct node *n) +{ + int ret; + + assert(n->state == STATE_CHECKED); + + info("Starting node %s", node_name_long(n)); + { INDENT + ret = n->_vt->start ? n->_vt->start(n) : -1; + if (ret) + return ret; + } + + n->state = STATE_STARTED; + + n->sequence = 0; + + return ret; +} + +int node_stop(struct node *n) +{ + int ret; + + assert(n->state == STATE_STARTED); + + info("Stopping node %s", node_name(n)); + { INDENT + ret = n->_vt->stop ? n->_vt->stop(n) : -1; + } + + if (ret == 0) + n->state = STATE_STOPPED; + + return ret; +} + +int node_destroy(struct node *n) +{ + assert(n->state != STATE_DESTROYED && n->state != STATE_STARTED); + + if (n->_vt->destroy) + n->_vt->destroy(n); + + list_remove(&n->_vt->instances, n); + + if (n->_vd) + free(n->_vd); + + if (n->_name) + free(n->_name); + + n->state = STATE_DESTROYED; + + return 0; } int node_read(struct node *n, struct sample *smps[], unsigned cnt) @@ -36,6 +148,9 @@ int node_read(struct node *n, struct sample *smps[], unsigned cnt) nread = n->_vt->read(n, smps, cnt); } + for (int i = 0; i < nread; i++) + smps[i]->source = n; + return nread; } @@ -58,88 +173,10 @@ int node_write(struct node *n, struct sample *smps[], unsigned cnt) return nsent; } -int node_init(struct node_type *vt, int argc, char *argv[], config_setting_t *cfg) -{ - int ret; - - if (vt->state != NODE_TYPE_UNINITIALIZED) - return -1; - - info("Initializing " YEL("%s") " node type", vt->name); - { INDENT - ret = vt->init ? vt->init(argc, argv, cfg) : -1; - } - - if (ret == 0) - vt->state = NODE_TYPE_INITIALIZED; - - return ret; -} - -int node_deinit(struct node_type *vt) -{ - int ret; - - if (vt->state != NODE_TYPE_INITIALIZED) - return -1; - - info("De-initializing " YEL("%s") " node type", vt->name); - { INDENT - ret = vt->deinit ? vt->deinit() : -1; - } - - if (ret == 0) - vt->state = NODE_TYPE_UNINITIALIZED; - - return ret; -} - -int node_start(struct node *n) -{ - int ret; - - if (n->state != NODE_CREATED && n->state != NODE_STOPPED) - return -1; - - n->state = NODE_STARTING; - - info("Starting node %s", node_name_long(n)); - { INDENT - ret = n->_vt->open ? n->_vt->open(n) : -1; - } - - if (ret == 0) - n->state = NODE_RUNNING; - - n->sequence = 0; - - return ret; -} - -int node_stop(struct node *n) -{ - int ret; - - if (n->state != NODE_RUNNING) - return -1; - - n->state = NODE_STOPPING; - - info("Stopping node %s", node_name(n)); - { INDENT - ret = n->_vt->close ? n->_vt->close(n) : -1; - } - - if (ret == 0) - n->state = NODE_STOPPED; - - return ret; -} - char * node_name(struct node *n) { if (!n->_name) - strcatf(&n->_name, RED("%s") "(" YEL("%s") ")", n->name, n->_vt->name); + strcatf(&n->_name, RED("%s") "(" YEL("%s") ")", n->name, plugin_name(n->_vt)); return n->_name; } @@ -164,41 +201,52 @@ const char * node_name_short(struct node *n) return n->name; } -const char * node_name_type(struct node *n) -{ - return n->_vt->name; -} - int node_reverse(struct node *n) { return n->_vt->reverse ? n->_vt->reverse(n) : -1; } -struct node * node_create(struct node_type *vt) +int node_parse_list(struct list *list, config_setting_t *cfg, struct list *all) { - struct node *n = alloc(sizeof(struct node)); - - list_push(&vt->instances, n); - - n->_vt = vt; - n->_vd = alloc(n->_vt->size); - - if (n->_vt->create) - n->_vt->create(n); + const char *str; + struct node *node; - n->state = NODE_CREATED; - - return n; -} - -void node_destroy(struct node *n) -{ - if (n->_vt->destroy) - n->_vt->destroy(n); - - list_remove(&n->_vt->instances, n); - - free(n->_vd); - free(n->_name); - free(n); + switch (config_setting_type(cfg)) { + case CONFIG_TYPE_STRING: + str = config_setting_get_string(cfg); + if (str) { + node = list_lookup(all, str); + if (node) + list_push(list, node); + else + cerror(cfg, "Unknown outgoing node '%s'", str); + } + else + cerror(cfg, "Invalid outgoing node"); + break; + + case CONFIG_TYPE_ARRAY: + for (int i = 0; i < config_setting_length(cfg); i++) { + config_setting_t *elm = config_setting_get_elem(cfg, i); + + str = config_setting_get_string(elm); + if (str) { + node = list_lookup(all, str); + if (!node) + cerror(elm, "Unknown outgoing node '%s'", str); + else if (node->_vt->write == NULL) + cerror(cfg, "Output node '%s' is not supported as a sink.", node_name(node)); + + list_push(list, node); + } + else + cerror(cfg, "Invalid outgoing node"); + } + break; + + default: + cerror(cfg, "Invalid output node(s)"); + } + + return list_length(list); } diff --git a/lib/node_type.c b/lib/node_type.c new file mode 100644 index 000000000..f92d05bc2 --- /dev/null +++ b/lib/node_type.c @@ -0,0 +1,51 @@ +/** Nodes. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#include +#include + +#include "sample.h" +#include "node.h" +#include "super_node.h" +#include "utils.h" +#include "config.h" +#include "plugin.h" + +int node_type_start(struct node_type *vt, int argc, char *argv[], config_setting_t *cfg) +{ + int ret; + + if (vt->state != STATE_STARTED) + return 0; + + info("Initializing " YEL("%s") " node type which is used by %zu nodes", plugin_name(vt), list_length(&vt->instances)); + { INDENT + ret = vt->init ? vt->init(argc, argv, cfg) : 0; + } + + if (ret == 0) + vt->state = STATE_STARTED; + + return ret; +} + +int node_type_stop(struct node_type *vt) +{ + int ret; + + if (vt->state != STATE_STARTED) + return 0; + + info("De-initializing " YEL("%s") " node type", plugin_name(vt)); + { INDENT + ret = vt->deinit ? vt->deinit() : -1; + } + + if (ret == 0) + vt->state = STATE_DESTROYED; + + return ret; +} diff --git a/lib/nodes/Makefile.inc b/lib/nodes/Makefile.inc new file mode 100644 index 000000000..20d41c0fb --- /dev/null +++ b/lib/nodes/Makefile.inc @@ -0,0 +1 @@ +LIB_SRC += $(wildcard lib/nodes/*.c) \ No newline at end of file diff --git a/lib/nodes/cbuilder.c b/lib/nodes/cbuilder.c index 14ef3a8d9..7910840e1 100644 --- a/lib/nodes/cbuilder.c +++ b/lib/nodes/cbuilder.c @@ -1,14 +1,15 @@ /** Node type: Wrapper around RSCAD CBuilder model * * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel **********************************************************************************/ #include "node.h" #include "log.h" -#include "nodes/cbuilder.h" +#include "plugin.h" +#include "utils.h" -struct list cbmodels; /**< Table of existing CBuilder models */ +#include "nodes/cbuilder.h" int cbuilder_parse(struct node *n, config_setting_t *cfg) { @@ -23,7 +24,7 @@ int cbuilder_parse(struct node *n, config_setting_t *cfg) if (!config_setting_lookup_string(cfg, "model", &model)) cerror(cfg, "CBuilder model requires 'model' setting"); - cb->model = list_lookup(&cbmodels, model); + cb->model = (struct cbuilder_model *) plugin_lookup(PLUGIN_TYPE_MODEL_CBUILDER, model); if (!cb->model) cerror(cfg, "Unknown model '%s'", model); @@ -42,7 +43,7 @@ int cbuilder_parse(struct node *n, config_setting_t *cfg) return 0; } -int cbuilder_open(struct node *n) +int cbuilder_start(struct node *n) { int ret; struct cbuilder *cb = n->_vd; @@ -64,7 +65,7 @@ int cbuilder_open(struct node *n) return 0; } -int cbuilder_close(struct node *n) +int cbuilder_stop(struct node *n) { struct cbuilder *cb = n->_vd; @@ -112,16 +113,20 @@ int cbuilder_write(struct node *n, struct sample *smps[], unsigned cnt) return 1; } -static struct node_type vt = { +static struct plugin p = { .name = "cbuilder", .description = "RTDS CBuilder model", - .vectorize = 1, - .size = sizeof(struct cbuilder), - .parse = cbuilder_parse, - .open = cbuilder_open, - .close = cbuilder_close, - .read = cbuilder_read, - .write = cbuilder_write, + .type = PLUGIN_TYPE_NODE, + .node = { + .vectorize = 1, + .size = sizeof(struct cbuilder), + .parse = cbuilder_parse, + .start = cbuilder_start, + .stop = cbuilder_stop, + .read = cbuilder_read, + .write = cbuilder_write, + .instances = LIST_INIT() + } }; -REGISTER_NODE_TYPE(&vt) +REGISTER_PLUGIN(&p) diff --git a/lib/nodes/file.c b/lib/nodes/file.c index 88256e912..0b540f486 100644 --- a/lib/nodes/file.c +++ b/lib/nodes/file.c @@ -1,7 +1,7 @@ /** Node type: File * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include @@ -11,6 +11,8 @@ #include "utils.h" #include "timing.h" #include "queue.h" +#include "plugin.h" +#include "sample_io.h" int file_reverse(struct node *n) { @@ -37,28 +39,28 @@ static char * file_format_name(const char *format, struct timespec *ts) return buf; } -static FILE * file_reopen(struct file_direction *dir) +static AFILE * file_reopen(struct file_direction *dir) { char buf[FILE_MAX_PATHLEN]; - const char *path = buf; + const char *uri = buf; /* Append chunk number to filename */ if (dir->chunk >= 0) - snprintf(buf, FILE_MAX_PATHLEN, "%s_%03u", dir->path, dir->chunk); + snprintf(buf, FILE_MAX_PATHLEN, "%s_%03u", dir->uri, dir->chunk); else - path = dir->path; + uri = dir->uri; if (dir->handle) - fclose(dir->handle); + afclose(dir->handle); - return fopen(path, dir->mode); + return afopen(uri, dir->mode); } static int file_parse_direction(config_setting_t *cfg, struct file *f, int d) { struct file_direction *dir = (d == FILE_READ) ? &f->read : &f->write; - if (!config_setting_lookup_string(cfg, "path", &dir->fmt)) + if (!config_setting_lookup_string(cfg, "uri", &dir->fmt)) return -1; if (!config_setting_lookup_string(cfg, "mode", &dir->mode)) @@ -138,7 +140,7 @@ char * file_print(struct node *n) } strcatf(&buf, "in=%s, epoch_mode=%s, epoch=%.2f, ", - f->read.path ? f->read.path : f->read.fmt, + f->read.uri ? f->read.uri : f->read.fmt, epoch_str, time_to_double(&f->read_epoch) ); @@ -149,7 +151,7 @@ char * file_print(struct node *n) if (f->write.fmt) { strcatf(&buf, "out=%s, mode=%s, ", - f->write.path ? f->write.path : f->write.fmt, + f->write.uri ? f->write.uri : f->write.fmt, f->write.mode ); } @@ -177,7 +179,7 @@ char * file_print(struct node *n) return buf; } -int file_open(struct node *n) +int file_start(struct node *n) { struct file *f = n->_vd; @@ -186,15 +188,15 @@ int file_open(struct node *n) if (f->read.fmt) { /* Prepare file name */ f->read.chunk = f->read.split ? 0 : -1; - f->read.path = file_format_name(f->read.fmt, &now); + f->read.uri = file_format_name(f->read.fmt, &now); /* Open file */ f->read.handle = file_reopen(&f->read); if (!f->read.handle) - serror("Failed to open file for reading: '%s'", f->read.path); + serror("Failed to open file for reading: '%s'", f->read.uri); /* Create timer */ - f->read_timer = (f->read_rate) + f->read_timer = f->read_rate ? timerfd_create_rate(f->read_rate) : timerfd_create(CLOCK_REALTIME, 0); if (f->read_timer < 0) @@ -205,7 +207,7 @@ int file_open(struct node *n) /* Get timestamp of first line */ struct sample s; - int ret = sample_fscan(f->read.handle, &s, NULL); rewind(f->read.handle); + int ret = sample_io_villas_fscan(f->read.handle->file, &s, NULL); arewind(f->read.handle); if (ret < 0) error("Failed to read first timestamp of node %s", node_name(n)); @@ -236,30 +238,30 @@ int file_open(struct node *n) if (f->write.fmt) { /* Prepare file name */ f->write.chunk = f->write.split ? 0 : -1; - f->write.path = file_format_name(f->write.fmt, &now); + f->write.uri = file_format_name(f->write.fmt, &now); /* Open file */ f->write.handle = file_reopen(&f->write); if (!f->write.handle) - serror("Failed to open file for writing: '%s'", f->write.path); + serror("Failed to open file for writing: '%s'", f->write.uri); } return 0; } -int file_close(struct node *n) +int file_stop(struct node *n) { struct file *f = n->_vd; - free(f->read.path); - free(f->write.path); + free(f->read.uri); + free(f->write.uri); if (f->read_timer) close(f->read_timer); if (f->read.handle) - fclose(f->read.handle); + afclose(f->read.handle); if (f->write.handle) - fclose(f->write.handle); + afclose(f->write.handle); return 0; } @@ -273,9 +275,9 @@ int file_read(struct node *n, struct sample *smps[], unsigned cnt) assert(f->read.handle); assert(cnt == 1); -retry: values = sample_fscan(f->read.handle, s, &flags); /* Get message and timestamp */ +retry: values = sample_io_villas_fscan(f->read.handle->file, s, &flags); /* Get message and timestamp */ if (values < 0) { - if (feof(f->read.handle)) { + if (afeof(f->read.handle)) { if (f->read.split) { f->read.chunk++; f->read.handle = file_reopen(&f->read); @@ -286,7 +288,7 @@ retry: values = sample_fscan(f->read.handle, s, &flags); /* Get message and time } else { info("Rewind input file of node %s", node_name(n)); - rewind(f->read.handle); + arewind(f->read.handle); goto retry; } } @@ -296,7 +298,7 @@ retry: values = sample_fscan(f->read.handle, s, &flags); /* Get message and time return 0; } - if (!f->read_rate || ftell(f->read.handle) == 0) { + if (!f->read_rate || aftell(f->read.handle) == 0) { s->ts.origin = time_add(&s->ts.origin, &f->read_offset); if (timerfd_wait_until(f->read_timer, &s->ts.origin) == 0) serror("Failed to wait for timer"); @@ -321,31 +323,35 @@ int file_write(struct node *n, struct sample *smps[], unsigned cnt) assert(cnt == 1); /* Split file if requested */ - if (f->write.split > 0 && ftell(f->write.handle) > f->write.split) { + if (f->write.split > 0 && aftell(f->write.handle) > f->write.split) { f->write.chunk++; f->write.handle = file_reopen(&f->write); info("Splitted output node %s: chunk=%u", node_name(n), f->write.chunk); } - sample_fprint(f->write.handle, s, SAMPLE_ALL & ~SAMPLE_OFFSET); - fflush(f->write.handle); + sample_io_villas_fprint(f->write.handle->file, s, SAMPLE_IO_ALL & ~SAMPLE_IO_OFFSET); + afflush(f->write.handle); return 1; } -static struct node_type vt = { +static struct plugin p = { .name = "file", .description = "support for file log / replay node type", - .vectorize = 1, - .size = sizeof(struct file), - .reverse = file_reverse, - .parse = file_parse, - .print = file_print, - .open = file_open, - .close = file_close, - .read = file_read, - .write = file_write + .type = PLUGIN_TYPE_NODE, + .node = { + .vectorize = 1, + .size = sizeof(struct file), + .reverse = file_reverse, + .parse = file_parse, + .print = file_print, + .start = file_start, + .stop = file_stop, + .read = file_read, + .write = file_write, + .instances = LIST_INIT() + } }; -REGISTER_NODE_TYPE(&vt) \ No newline at end of file +REGISTER_PLUGIN(&p) \ No newline at end of file diff --git a/lib/nodes/fpga.c b/lib/nodes/fpga.c index 9b2ac4f60..4d8b984e0 100644 --- a/lib/nodes/fpga.c +++ b/lib/nodes/fpga.c @@ -1,14 +1,11 @@ /** Node type: VILLASfpga * * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel *********************************************************************************/ #include #include -#include -#include -#include #include "kernel/kernel.h" #include "kernel/pci.h" @@ -18,74 +15,25 @@ #include "config.h" #include "utils.h" #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) { - 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("BAR0 mapped at %p", fpga.map); - - info("IP blocks:"); - list_foreach(struct ip *i, &f->ips) { INDENT - ip_dump(i); - } - } - - vfio_dump(fpga.vd.group->container); + struct fpga_card *c = f->ip->card; + + fpga_card_dump(c); } -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,135 +42,37 @@ 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; } -int fpga_init(int argc, char * argv[], config_setting_t *cfg) +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,92 +81,109 @@ 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; } -int fpga_open(struct node *n) +int fpga_start(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; } @@ -324,25 +191,25 @@ int fpga_open(struct node *n) return 0; } -int fpga_close(struct node *n) +int fpga_stop(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 +219,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 +231,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 +258,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 +281,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; } @@ -429,19 +289,28 @@ int fpga_write(struct node *n, struct sample *smps[], unsigned cnt) return -1; } -static struct node_type vt = { +struct fpga_card * fpga_lookup_card(const char *name) +{ + return (struct fpga_card *) list_lookup(&cards, name); +} + +static struct plugin p = { .name = "fpga", .description = "VILLASfpga PCIe card (libxil)", - .size = sizeof(struct fpga_dm), - .vectorize = 1, - .parse = fpga_parse, - .print = fpga_print, - .open = fpga_open, - .close = fpga_close, - .read = fpga_read, - .write = fpga_write, - .init = fpga_init, - .deinit = fpga_deinit + .type = PLUGIN_TYPE_NODE, + .node = { + .size = sizeof(struct fpga), + .vectorize = 1, + .parse = fpga_parse, + .print = fpga_print, + .start = fpga_start, + .stop = fpga_stop, + .read = fpga_read, + .write = fpga_write, + .init = fpga_init, + .deinit = fpga_deinit, + .instances = LIST_INIT() + } }; -REGISTER_NODE_TYPE(&vt) +REGISTER_PLUGIN(&p) \ No newline at end of file diff --git a/lib/nodes/ngsi.c b/lib/nodes/ngsi.c index fc46694da..9fb660c30 100644 --- a/lib/nodes/ngsi.c +++ b/lib/nodes/ngsi.c @@ -1,7 +1,7 @@ /** Node type: OMA Next Generation Services Interface 10 (NGSI) (FIWARE context broker) * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC **********************************************************************************/ #include @@ -9,7 +9,6 @@ #include #include -#include #include #include @@ -17,6 +16,7 @@ #include "utils.h" #include "timing.h" +#include "plugin.h" /* Some global settings */ static char *name = NULL; @@ -56,7 +56,10 @@ static json_t* ngsi_build_entity(struct ngsi *i, struct sample *smps[], unsigned if (flags & NGSI_ENTITY_ATTRIBUTES) { json_t *attributes = json_array(); - list_foreach(struct ngsi_attribute *map, &i->mapping) { + + for (size_t j = 0; j < list_length(&i->mapping); j++) { + struct ngsi_attribute *map = list_at(&i->mapping, j); + json_t *attribute = json_pack("{ s: s, s: s }", "name", map->name, "type", map->type @@ -77,7 +80,10 @@ static json_t* ngsi_build_entity(struct ngsi *i, struct sample *smps[], unsigned if (flags & NGSI_ENTITY_METADATA) { /* Create Metadata for attribute */ json_t *metadatas = json_array(); - list_foreach(struct ngsi_metadata *meta, &map->metadata) { + + for (size_t i = 0; i < list_length(&map->metadata); i++) { + struct ngsi_metadata *meta = list_at(&map->metadata, i); + json_array_append_new(metadatas, json_pack("{ s: s, s: s, s: s }", "name", meta->name, "type", meta->type, @@ -201,7 +207,7 @@ static int ngsi_parse_mapping(struct list *mapping, config_setting_t *cfg) list_init(&map.metadata); struct ngsi_metadata meta; while (sscanf(token, " %m[^(](%m[^)])=%ms%n", &meta.name, &meta.type, &meta.value, &bytes) == 3) { INDENT - list_push(&map.metadata, memdup(&meta, sizeof(struct ngsi_metadata))); + list_push(&map.metadata, memdup(&meta, sizeof(meta))); token += bytes; } @@ -219,10 +225,10 @@ static int ngsi_parse_mapping(struct list *mapping, config_setting_t *cfg) }; snprintf(index.value, 8, "%u", j); - list_push(&map.metadata, memdup(&index, sizeof(struct ngsi_metadata))); - list_push(&map.metadata, memdup(&source, sizeof(struct ngsi_metadata))); + list_push(&map.metadata, memdup(&index, sizeof(index))); + list_push(&map.metadata, memdup(&source, sizeof(source))); - list_push(mapping, memdup(&map, sizeof(struct ngsi_attribute))); + list_push(mapping, memdup(&map, sizeof(map))); } return 0; @@ -285,7 +291,7 @@ static int ngsi_request(CURL *handle, const char *endpoint, const char *operatio curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, strlen(post)); curl_easy_setopt(handle, CURLOPT_POSTFIELDS, post); - debug(DBG_NGSI | 18, "Request to context broker: %s\n%s", url, post); + debug(LOG_NGSI | 18, "Request to context broker: %s\n%s", url, post); /* We don't want to leave the handle in an invalid state */ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old); @@ -299,8 +305,8 @@ static int ngsi_request(CURL *handle, const char *endpoint, const char *operatio curl_easy_getinfo(handle, CURLINFO_TOTAL_TIME, &time); - debug(DBG_NGSI | 16, "Request to context broker completed in %.4f seconds", time); - debug(DBG_NGSI | 17, "Response from context broker:\n%s", chunk.data); + debug(LOG_NGSI | 16, "Request to context broker completed in %.4f seconds", time); + debug(LOG_NGSI | 17, "Response from context broker:\n%s", chunk.data); *response = json_loads(chunk.data, 0, &err); if (!*response) @@ -427,31 +433,35 @@ char * ngsi_print(struct node *n) i->endpoint, i->timeout, list_length(&i->mapping)); } -static void ngsi_destroy_metadata(struct ngsi_metadata *meta) +static int ngsi_metadata_destroy(struct ngsi_metadata *meta) { free(meta->value); free(meta->name); free(meta->type); + + return 0; } -static void ngsi_destroy_attribute(struct ngsi_attribute *attr) +static int ngsi_attribute_destroy(struct ngsi_attribute *attr) { free(attr->name); free(attr->type); - list_destroy(&attr->metadata, (dtor_cb_t) ngsi_destroy_metadata, true); + list_destroy(&attr->metadata, (dtor_cb_t) ngsi_metadata_destroy, true); + + return 0; } int ngsi_destroy(struct node *n) { struct ngsi *i = n->_vd; - list_destroy(&i->mapping, (dtor_cb_t) ngsi_destroy_attribute, true); + list_destroy(&i->mapping, (dtor_cb_t) ngsi_attribute_destroy, true); return 0; } -int ngsi_open(struct node *n) +int ngsi_start(struct node *n) { struct ngsi *i = n->_vd; int ret; @@ -473,13 +483,13 @@ int ngsi_open(struct node *n) if (i->tfd < 0) serror("Failed to create timer"); - i->headers = curl_slist_append(i->headers, "User-Agent: VILLASnode " VERSION); i->headers = curl_slist_append(i->headers, "Accept: application/json"); i->headers = curl_slist_append(i->headers, "Content-Type: application/json"); curl_easy_setopt(i->curl, CURLOPT_SSL_VERIFYPEER, i->ssl_verify); curl_easy_setopt(i->curl, CURLOPT_TIMEOUT_MS, i->timeout * 1e3); curl_easy_setopt(i->curl, CURLOPT_HTTPHEADER, i->headers); + curl_easy_setopt(i->curl, CURLOPT_USERAGENT, USER_AGENT); /* Create entity and atributes */ json_t *entity = ngsi_build_entity(i, NULL, 0, NGSI_ENTITY_METADATA); @@ -493,7 +503,7 @@ int ngsi_open(struct node *n) return ret; } -int ngsi_close(struct node *n) +int ngsi_stop(struct node *n) { struct ngsi *i = n->_vd; int ret; @@ -550,19 +560,23 @@ int ngsi_write(struct node *n, struct sample *smps[], unsigned cnt) return ret ? 0 : cnt; } -static struct node_type vt = { +static struct plugin p = { .name = "ngsi", .description = "OMA Next Generation Services Interface 10 (libcurl, libjansson)", - .vectorize = 0, /* unlimited */ - .size = sizeof(struct ngsi), - .parse = ngsi_parse, - .print = ngsi_print, - .open = ngsi_open, - .close = ngsi_close, - .read = ngsi_read, - .write = ngsi_write, - .init = ngsi_init, - .deinit = ngsi_deinit + .type = PLUGIN_TYPE_NODE, + .node = { + .vectorize = 0, /* unlimited */ + .size = sizeof(struct ngsi), + .parse = ngsi_parse, + .print = ngsi_print, + .start = ngsi_start, + .stop = ngsi_stop, + .read = ngsi_read, + .write = ngsi_write, + .init = ngsi_init, + .deinit = ngsi_deinit, + .instances = LIST_INIT() + } }; -REGISTER_NODE_TYPE(&vt) +REGISTER_PLUGIN(&p) \ No newline at end of file diff --git a/lib/nodes/opal.c b/lib/nodes/opal.c index e11d5c904..202198d4a 100644 --- a/lib/nodes/opal.c +++ b/lib/nodes/opal.c @@ -3,7 +3,7 @@ * This file implements the opal subtype for nodes. * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include @@ -11,6 +11,7 @@ #include "opal.h" #include "utils.h" +#incude "plugin.h" /* Private static storage */ static char *async_shmem_name; /**< Shared Memory identifiers and size, provided via argv. */ @@ -71,7 +72,7 @@ int opal_init(int argc, char *argv[], config_setting_t *cfg) info("Started as OPAL Asynchronous process"); info("This is VILLASnode %s (built on %s, %s)", - VERSION, __DATE__, __TIME__); + VERSION_STR, __DATE__, __TIME__); opal_print_global(); @@ -86,7 +87,7 @@ int opal_deinit() if (err != EOK) error("Failed to close shared memory area (%d)", err); - debug(DBG_OPAL | 4, "Closing OPAL shared memory mapping"); + debug(LOG_OPAL | 4, "Closing OPAL shared memory mapping"); err = OpalSystemCtrl_UnRegister(print_shmem_name); if (err != EOK) @@ -102,7 +103,7 @@ int opal_deinit() int opal_print_global() { - debug(DBG_OPAL | 2, "Controller ID: %u", params.controllerID); + debug(LOG_OPAL | 2, "Controller ID: %u", params.controllerID); char *sbuf = alloc(send_icons * 5); char *rbuf = alloc(recv_icons * 5); @@ -112,17 +113,17 @@ int opal_print_global() for (int i = 0; i < recv_icons; i++) strcatf(&rbuf, "%u ", recv_ids[i]); - debug(DBG_OPAL | 2, "Send Blocks: %s", sbuf); - debug(DBG_OPAL | 2, "Receive Blocks: %s", rbuf); + debug(LOG_OPAL | 2, "Send Blocks: %s", sbuf); + debug(LOG_OPAL | 2, "Receive Blocks: %s", rbuf); free(sbuf); free(rbuf); - debug(DBG_OPAL | 2, "Control Block Parameters:"); + debug(LOG_OPAL | 2, "Control Block Parameters:"); for (int i = 0; i < GENASYNC_NB_FLOAT_PARAM; i++) - debug(DBG_OPAL | 2, "FloatParam[]%u] = %f", i, params.FloatParam[i]); + debug(LOG_OPAL | 2, "FloatParam[]%u] = %f", i, params.FloatParam[i]); for (int i = 0; i < GENASYNC_NB_STRING_PARAM; i++) - debug(DBG_OPAL | 2, "StringParam[%u] = %s", i, params.StringParam[i]); + debug(LOG_OPAL | 2, "StringParam[%u] = %s", i, params.StringParam[i]); return 0; } @@ -148,7 +149,7 @@ char * opal_print(struct node *n) o->send_id, o->recv_id, o->reply); } -int opal_open(struct node *n) +int opal_start(struct node *n) { struct opal *o = n->_vd; @@ -172,7 +173,7 @@ int opal_open(struct node *n) return 0; } -int opal_close(struct node *n) +int opal_stop(struct node *n) { return 0; } @@ -275,19 +276,23 @@ int opal_write(struct node *n, struct pool *pool, unsigned cnt) return 1; } -static struct node_type vt = { +static struct plugin p = { .name = "opal", .description = "run as OPAL Asynchronous Process (libOpalAsyncApi)", - .vectoroize = 1, - .size = sizeof(struct opal), - .parse = opal_parse, - .print = opal_print, - .open = opal_open, - .close = opal_close, - .read = opal_read, - .write = opal_write, - .init = opal_init, - .deinit = opal_deinit + .type = PLUGIN_TYPE_NODE, + .node = { + .vectoroize = 1, + .size = sizeof(struct opal), + .parse = opal_parse, + .print = opal_print, + .start = opal_start, + .stop = opal_stop, + .read = opal_read, + .write = opal_write, + .init = opal_init, + .deinit = opal_deinit, + .instances = LIST_INIT() + } }; -REGISTER_NODE_TYPE(&vt) \ No newline at end of file +REGISTER_PLUGIN(&p) \ No newline at end of file diff --git a/lib/nodes/socket.c b/lib/nodes/socket.c index 2ffaf343f..87e7464db 100644 --- a/lib/nodes/socket.c +++ b/lib/nodes/socket.c @@ -1,20 +1,13 @@ /** Various socket related functions * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ -#include #include - -#include #include -#include -#include - -#include #include -#include +#include #include #ifdef __linux__ @@ -35,23 +28,25 @@ #include "msg.h" #include "sample.h" #include "queue.h" +#include "plugin.h" /* Forward declartions */ -static struct node_type vt; +static struct plugin p; /* Private static storage */ struct list interfaces; -int socket_init(int argc, char * argv[], config_setting_t *cfg) +int socket_init(int argc, char *argv[], config_setting_t *cfg) { if (getuid() != 0) - error("The 'socket' node-type requires superuser privileges!"); + error("The 'socket' node-type requires super-user privileges!"); nl_init(); /* Fill link cache */ list_init(&interfaces); /* Gather list of used network interfaces */ - list_foreach(struct node *n, &vt.instances) { + for (size_t i = 0; i < list_length(&p.node.instances); i++) { + struct node *n = list_at(&p.node.instances, i); struct socket *s = n->_vd; struct rtnl_link *link; @@ -64,14 +59,21 @@ int socket_init(int argc, char * argv[], config_setting_t *cfg) /* Search of existing interface with correct ifindex */ struct interface *i; - list_foreach(i, &interfaces) { + + for (size_t k = 0; k < list_length(&interfaces); k++) { + i = list_at(&interfaces, k); + if (rtnl_link_get_ifindex(i->nl_link) == rtnl_link_get_ifindex(link)) goto found; } /* If not found, create a new interface */ - i = if_create(link); - list_push(&interfaces, i); + struct interface j; + + if_init(&j, link); + + list_push(&interfaces, memdup(&j, sizeof(j))); + i = &j; found: list_push(&i->sockets, s); } @@ -81,16 +83,22 @@ found: list_push(&i->sockets, s); if (!config_setting_lookup_int(cfg, "affinity", &affinity)) affinity = -1; - list_foreach(struct interface *i, &interfaces) + for (size_t j = 0; list_length(&interfaces); j++) { + struct interface *i = list_at(&interfaces, j); + if_start(i, affinity); + } return 0; } int socket_deinit() { - list_foreach(struct interface *i, &interfaces) + for (size_t j = 0; list_length(&interfaces); j++) { + struct interface *i = list_at(&interfaces, j); + if_stop(i); + } list_destroy(&interfaces, (dtor_cb_t) if_destroy, false); @@ -116,11 +124,12 @@ char * socket_print(struct node *n) if (s->header == SOCKET_HEADER_DEFAULT) endian = "auto"; - else + else { switch (s->endian) { case MSG_ENDIAN_LITTLE: endian = "little"; break; case MSG_ENDIAN_BIG: endian = "big"; break; } + } char *local = socket_print_addr((struct sockaddr *) &s->local); char *remote = socket_print_addr((struct sockaddr *) &s->remote); @@ -133,7 +142,7 @@ char * socket_print(struct node *n) return buf; } -int socket_open(struct node *n) +int socket_start(struct node *n) { struct socket *s = n->_vd; struct sockaddr_in *sin = (struct sockaddr_in *) &s->local; @@ -163,7 +172,7 @@ int socket_open(struct node *n) if (ret) serror("Failed to set FW mark for outgoing packets"); else - debug(DBG_SOCKET | 4, "Set FW mark for socket (sd=%u) to %u", s->sd, s->mark); + debug(LOG_SOCKET | 4, "Set FW mark for socket (sd=%u) to %u", s->sd, s->mark); } /* Set socket priority, QoS or TOS IP options */ @@ -175,7 +184,7 @@ int socket_open(struct node *n) if (setsockopt(s->sd, IPPROTO_IP, IP_TOS, &prio, sizeof(prio))) serror("Failed to set type of service (QoS)"); else - debug(DBG_SOCKET | 4, "Set QoS/TOS IP option for node %s to %#x", node_name(n), prio); + debug(LOG_SOCKET | 4, "Set QoS/TOS IP option for node %s to %#x", node_name(n), prio); break; default: @@ -183,7 +192,7 @@ int socket_open(struct node *n) if (setsockopt(s->sd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio))) serror("Failed to set socket priority"); else - debug(DBG_SOCKET | 4, "Set socket priority for node %s to %d", node_name(n), prio); + debug(LOG_SOCKET | 4, "Set socket priority for node %s to %d", node_name(n), prio); break; } @@ -202,7 +211,7 @@ int socket_reverse(struct node *n) return 0; } -int socket_close(struct node *n) +int socket_stop(struct node *n) { struct socket *s = n->_vd; @@ -386,7 +395,7 @@ int socket_read(struct node *n, struct sample *smps[], unsigned cnt) } } - debug(DBG_SOCKET | 17, "Received message of %zd bytes: %u samples", bytes, received); + debug(LOG_SOCKET | 17, "Received message of %zd bytes: %u samples", bytes, received); return received; } @@ -428,7 +437,7 @@ int socket_write(struct node *n, struct sample *smps[], unsigned cnt) sent++; - debug(DBG_SOCKET | 17, "Sent packet of %zd bytes with 1 sample", bytes); + debug(LOG_SOCKET | 17, "Sent packet of %zd bytes with 1 sample", bytes); } } else { @@ -462,7 +471,7 @@ int socket_write(struct node *n, struct sample *smps[], unsigned cnt) sent = cnt; /** @todo Find better way to determine how many values we actually sent */ - debug(DBG_SOCKET | 17, "Sent packet of %zd bytes with %u samples", bytes, cnt); + debug(LOG_SOCKET | 17, "Sent packet of %zd bytes with %u samples", bytes, cnt); } return sent; @@ -675,21 +684,25 @@ int socket_parse_addr(const char *addr, struct sockaddr *saddr, enum socket_laye return ret; } -static struct node_type vt = { +static struct plugin p = { .name = "socket", .description = "BSD network sockets", - .vectorize = 0, - .size = sizeof(struct socket), - .destroy = socket_destroy, - .reverse = socket_reverse, - .parse = socket_parse, - .print = socket_print, - .open = socket_open, - .close = socket_close, - .read = socket_read, - .write = socket_write, - .init = socket_init, - .deinit = socket_deinit + .type = PLUGIN_TYPE_NODE, + .node = { + .vectorize = 0, + .size = sizeof(struct socket), + .destroy = socket_destroy, + .reverse = socket_reverse, + .parse = socket_parse, + .print = socket_print, + .start = socket_start, + .stop = socket_stop, + .read = socket_read, + .write = socket_write, + .init = socket_init, + .deinit = socket_deinit, + .instances = LIST_INIT() + } }; -REGISTER_NODE_TYPE(&vt) +REGISTER_PLUGIN(&p) \ No newline at end of file diff --git a/lib/nodes/websocket.c b/lib/nodes/websocket.c index f23c06e0d..8ef9e10ee 100644 --- a/lib/nodes/websocket.c +++ b/lib/nodes/websocket.c @@ -1,7 +1,7 @@ /** Node type: Websockets (libwebsockets) * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include @@ -10,236 +10,117 @@ #include #include -#include #include -#include "nodes/websocket.h" +#include "super_node.h" +#include "webmsg_format.h" #include "timing.h" #include "utils.h" -#include "msg.h" -#include "cfg.h" #include "config.h" +#include "plugin.h" + +#include "nodes/websocket.h" + +/* Internal datastructures */ +struct destination { + char *uri; + struct lws_client_connect_info info; +}; /* Private static storage */ -static config_setting_t *cfg_root; /**< Root config */ -static pthread_t thread; /**< All nodes are served by a single websocket server. This server is running in a dedicated thread. */ -static struct lws_context *context; /**< The libwebsockets server context. */ +static int id = 0; /**< Highest assigned ID to websocket nodes. */ -static int port; /**< Port of the build in HTTP / WebSocket server */ - -static const char *ssl_cert; /**< Path to the SSL certitifcate for HTTPS / WSS */ -static const char *ssl_private_key; /**< Path to the SSL private key for HTTPS / WSS */ -static const char *htdocs; /**< Path to the directory which should be served by build in HTTP server */ +struct list connections; /**< List of active libwebsocket connections which receive samples from all nodes (catch all) */ /* Forward declarations */ -static struct node_type vt; -static int protocol_cb_http(struct lws *, enum lws_callback_reasons, void *, void *, size_t); -static int protocol_cb_live(struct lws *, enum lws_callback_reasons, void *, void *, size_t); +static struct plugin p; -static struct lws_protocols protocols[] = { - { - "http-only", - protocol_cb_http, - 0, - 0 - }, - { - "live", - protocol_cb_live, - sizeof(struct websocket_connection), - 0 - }, - { 0 /* terminator */ } -}; +__attribute__((unused)) static int websocket_connection_init(struct websocket_connection *c) +{ + /** @todo */ + return -1; +} -#if 0 -static const struct lws_extension exts[] = { - { - "permessage-deflate", - lws_extension_callback_pm_deflate, - "permessage-deflate" - }, - { - "deflate-frame", - lws_extension_callback_pm_deflate, - "deflate_frame" - }, - { NULL, NULL, NULL /* terminator */ } -}; -#endif +__attribute__((unused)) static void websocket_connection_destroy(struct websocket_connection *c) +{ + if (c->_name) + free(c->_name); +} -static void logger(int level, const char *msg) { - int len = strlen(msg); - if (strchr(msg, '\n')) - len -= 1; - - /* Decrease severity for some errors. */ - if (strstr(msg, "Unable to open") == msg) - level = LLL_WARN; - - switch (level) { - case LLL_ERR: error("LWS: %.*s", len, msg); break; - case LLL_WARN: warn("LWS: %.*s", len, msg); break; - case LLL_INFO: info("LWS: %.*s", len, msg); break; - default: debug(DBG_WEBSOCKET | 1, "LWS: %.*s", len, msg); break; +static char * websocket_connection_name(struct websocket_connection *c) +{ + if (!c->_name) { + if (c->node) + asprintf(&c->_name, "%s (%s) for node %s", c->peer.name, c->peer.ip, node_name(c->node)); + else + asprintf(&c->_name, "%s (%s) for all nodes", c->peer.name, c->peer.ip); } + + return c->_name; } -static void * server_thread(void *ctx) +static int websocket_connection_write(struct websocket_connection *c, struct sample *smps[], unsigned cnt) { - debug(DBG_WEBSOCKET | 3, "WebSocket: Started server thread"); + int blocks, enqueued; + char *bufs[cnt]; - while (lws_service(context, 10) >= 0); + struct websocket *w = c->node->_vd; + + switch (c->state) { + case WEBSOCKET_SHUTDOWN: + return -1; + case WEBSOCKET_CLOSED: + if (c->node) { + struct websocket *w = c->node->_vd; + list_remove(&w->connections, c); + } + else + list_remove(&connections, c); + break; + + case WEBSOCKET_ESTABLISHED: + c->state = WEBSOCKET_ACTIVE; + /* fall through */ + + case WEBSOCKET_ACTIVE: + blocks = pool_get_many(&w->pool, (void **) bufs, cnt); + if (blocks != cnt) + warn("Pool underrun in websocket connection: %s", websocket_connection_name(c)); + + for (int i = 0; i < blocks; i++) { + struct webmsg *msg = (struct webmsg *) (bufs[i] + LWS_PRE); - debug(DBG_WEBSOCKET | 3, "WebSocket: shutdown voluntarily"); + msg->version = WEBMSG_VERSION; + msg->type = WEBMSG_TYPE_DATA; + msg->endian = WEBMSG_ENDIAN_HOST; + msg->length = smps[i]->length; + msg->sequence = smps[i]->sequence; + msg->id = w->id; + msg->ts.sec = smps[i]->ts.origin.tv_sec; + msg->ts.nsec = smps[i]->ts.origin.tv_nsec; - return NULL; -} - -/* Choose mime type based on the file extension */ -static char * get_mimetype(const char *resource_path) -{ - char *extension = strrchr(resource_path, '.'); - - if (extension == NULL) - return "text/plain"; - else if (!strcmp(extension, ".png")) - return "image/png"; - else if (!strcmp(extension, ".svg")) - return "image/svg+xml"; - else if (!strcmp(extension, ".jpg")) - return "image/jpg"; - else if (!strcmp(extension, ".gif")) - return "image/gif"; - else if (!strcmp(extension, ".html")) - return "text/html"; - else if (!strcmp(extension, ".css")) - return "text/css"; - else if (!strcmp(extension, ".js")) - return "application/javascript"; - else - return "text/plain"; -} - -int protocol_cb_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) -{ - switch (reason) { - case LWS_CALLBACK_HTTP: - if (!htdocs) { - lws_return_http_status(wsi, HTTP_STATUS_SERVICE_UNAVAILABLE, NULL); - goto try_to_reuse; + memcpy(&msg->data, &smps[i]->data, smps[i]->length * 4); } - if (len < 1) { - lws_return_http_status(wsi, HTTP_STATUS_BAD_REQUEST, NULL); - goto try_to_reuse; - } - - char *requested_uri = (char *) in; + enqueued = queue_push_many(&c->queue, (void **) bufs, cnt); + if (enqueued != blocks) + warn("Queue overrun in websocket connection: %s", websocket_connection_name(c)); - debug(DBG_WEBSOCKET | 3, "LWS: New HTTP request: %s", requested_uri); - - /* Handle default path */ - if (!strcmp(requested_uri, "/")) { - char *response = "HTTP/1.1 302 Found\r\n" - "Content-Length: 0\r\n" - "Location: /index.html\r\n" - "\r\n"; - - lws_write(wsi, (void *) response, strlen(response), LWS_WRITE_HTTP); - - goto try_to_reuse; - } -#ifdef WITH_JANSSON - /* Return list of websocket nodes */ - else if (!strcmp(requested_uri, "/nodes.json")) { - json_t *json_body = json_array(); - - list_foreach(struct node *n, &vt.instances) { - struct websocket *w = n->_vd; - - json_t *json_node = json_pack("{ s: s, s: i, s: i, s: i, s: i }", - "name", node_name_short(n), - "connections", list_length(&w->connections), - "state", n->state, - "vectorize", n->vectorize, - "affinity", n->affinity - ); - - /* Add all additional fields of node here. - * This can be used for metadata */ - json_object_update(json_node, config_to_json(n->cfg)); - - json_array_append_new(json_body, json_node); - } - - char *body = json_dumps(json_body, JSON_INDENT(4)); - - char *header = "HTTP/1.1 200 OK\r\n" - "Connection: close\r\n" - "Content-Type: application/json\r\n" - "\r\n"; - - lws_write(wsi, (void *) header, strlen(header), LWS_WRITE_HTTP); - lws_write(wsi, (void *) body, strlen(body), LWS_WRITE_HTTP); - - free(body); - json_decref(json_body); - - return -1; - } - else if (!strcmp(requested_uri, "/config.json")) { - char *body = json_dumps(config_to_json(cfg_root), JSON_INDENT(4)); - - char *header = "HTTP/1.1 200 OK\r\n" - "Connection: close\r\n" - "Content-Type: application/json\r\n" - "\r\n"; - - lws_write(wsi, (void *) header, strlen(header), LWS_WRITE_HTTP); - lws_write(wsi, (void *) body, strlen(body), LWS_WRITE_HTTP); - - free(body); - - return -1; - } -#endif - else { - char path[4069]; - snprintf(path, sizeof(path), "%s%s", htdocs, requested_uri); - - /* refuse to serve files we don't understand */ - char *mimetype = get_mimetype(path); - if (!mimetype) { - warn("HTTP: Unknown mimetype for %s", path); - lws_return_http_status(wsi, HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, NULL); - return -1; - } - - int n = lws_serve_http_file(wsi, path, mimetype, NULL, 0); - if (n < 0) - return -1; - else if (n == 0) - break; - else - goto try_to_reuse; - } - - default: + lws_callback_on_writable(c->wsi); break; } - - return 0; -try_to_reuse: - if (lws_http_transaction_completed(wsi)) - return -1; - return 0; } -int protocol_cb_live(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) +static void websocket_destination_destroy(struct destination *d) { + free(d->uri); +} + +int websocket_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) +{ + int ret; struct websocket_connection *c = user; struct websocket *w; @@ -254,73 +135,88 @@ int protocol_cb_live(struct lws *wsi, enum lws_callback_reasons reason, void *us return -1; } - /* Search for node whose name matches the URI. */ - c->node = list_lookup(&vt.instances, uri + 1); - if (c->node == NULL) { - warn("LWS: Closing Connection for non-existent node: %s", uri + 1); - return -1; + if ((uri[0] == '/' && uri[1] == 0) || uri[0] == 0){ + /* Catch all connection */ + c->node = NULL; } + else { + char *node = uri + 1; - /* Check if node is running */ - if (c->node->state != NODE_RUNNING) - return -1; + /* Search for node whose name matches the URI. */ + c->node = list_lookup(&p.node.instances, node); + if (c->node == NULL) { + warn("LWS: Closing Connection for non-existent node: %s", uri + 1); + return -1; + } + + /* Check if node is running */ + if (c->node->state != STATE_STARTED) + return -1; + } c->state = WEBSOCKET_ESTABLISHED; c->wsi = wsi; + + ret = queue_init(&c->queue, DEFAULT_QUEUELEN, &memtype_hugepage); + if (ret) { + warn("Failed to create queue for incoming websocket connection. Closing.."); + return -1; + } /* Lookup peer address for debug output */ lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), c->peer.name, sizeof(c->peer.name), c->peer.ip, sizeof(c->peer.ip)); - info("LWS: New Connection for node %s from %s (%s)", node_name(c->node), c->peer.name, c->peer.ip); + info("LWS: New connection %s", websocket_connection_name(c)); - struct websocket *w = (struct websocket *) c->node->_vd; - list_push(&w->connections, c); + if (c->node != NULL) { + struct websocket *w = c->node->_vd; + list_push(&w->connections, c); + } + else { + list_push(&connections, c); + } return 0; } case LWS_CALLBACK_CLOSED: - info("LWS: Connection closed for node %s from %s (%s)", node_name(c->node), c->peer.name, c->peer.ip); + info("LWS: Connection %s closed", websocket_connection_name(c)); c->state = WEBSOCKET_CLOSED; c->wsi = NULL; + + queue_destroy(&c->queue); return 0; case LWS_CALLBACK_CLIENT_WRITEABLE: case LWS_CALLBACK_SERVER_WRITEABLE: { - w = (struct websocket *) c->node->_vd; + w = c->node->_vd; - if (c->node->state != NODE_RUNNING) + if (c->node && c->node->state != STATE_STARTED) return -1; - if (w->shutdown) { - lws_close_reason(wsi, LWS_CLOSE_STATUS_GOINGAWAY, (unsigned char *) "Bye", 4); + if (c->state == WEBSOCKET_SHUTDOWN) { + lws_close_reason(wsi, LWS_CLOSE_STATUS_GOINGAWAY, (unsigned char *) "Node stopped", 4); return -1; } - - - int cnt, sent, ret; - unsigned char *bufs[DEFAULT_QUEUELEN]; - - cnt = queue_get_many(&w->queue_tx, (void **) bufs, DEFAULT_QUEUELEN, c->sent); - for (sent = 0; sent < cnt; sent++) { - struct msg *msg = (struct msg *) (bufs[sent] + LWS_PRE); + char *buf; + int cnt; + while ((cnt = queue_pull(&c->queue, (void **) &buf))) { + struct webmsg *msg = (struct webmsg *) (buf + LWS_PRE); - ret = lws_write(wsi, (unsigned char *) msg, MSG_LEN(msg->length), LWS_WRITE_BINARY); - if (ret < MSG_LEN(msg->length)) + pool_put(&w->pool, (void *) buf); + + ret = lws_write(wsi, (unsigned char *) msg, WEBMSG_LEN(msg->length), LWS_WRITE_BINARY); + if (ret < WEBMSG_LEN(msg->length)) error("Failed lws_write()"); if (lws_send_pipe_choked(wsi)) - break; + break; } - - queue_pull_many(&w->queue_tx, (void **) bufs, sent, &c->sent); - - pool_put_many(&w->pool, (void **) bufs, sent); - if (sent < cnt) + if (queue_available(&c->queue) > 0) lws_callback_on_writable(wsi); return 0; @@ -328,32 +224,35 @@ int protocol_cb_live(struct lws *wsi, enum lws_callback_reasons reason, void *us case LWS_CALLBACK_CLIENT_RECEIVE: case LWS_CALLBACK_RECEIVE: { - w = (struct websocket *) c->node->_vd; + w = c->node->_vd; - if (c->node->state != NODE_RUNNING) + if (c->node->state != STATE_STARTED) return -1; - if (!lws_frame_is_binary(wsi) || len < MSG_LEN(0)) - warn("LWS: Received invalid packet for node: %s", node_name(c->node)); + if (!lws_frame_is_binary(wsi) || len < WEBMSG_LEN(0)) + warn("LWS: Received invalid packet for connection %s", websocket_connection_name(c)); - struct msg *msg = (struct msg *) in; + struct webmsg *msg = (struct webmsg *) in; - while ((char *) msg + MSG_LEN(msg->length) <= (char *) in + len) { - struct msg *msg2 = pool_get(&w->pool); + while ((char *) msg + WEBMSG_LEN(msg->length) <= (char *) in + len) { + struct webmsg *msg2 = pool_get(&w->pool); if (!msg2) { - warn("Pool underrun for node: %s", node_name(c->node)); - return -1; + warn("Pool underrun for connection %s", websocket_connection_name(c)); + break; } - memcpy(msg2, msg, MSG_LEN(msg->length)); + memcpy(msg2, msg, WEBMSG_LEN(msg->length)); - queue_push(&w->queue_rx, msg2, &c->received); + ret = queue_push(&w->queue, msg2); + if (ret != 1) { + warn("Queue overrun for connection %s", websocket_connection_name(c)); + break; + } /* Next message */ - msg = (struct msg *) ((char *) msg + MSG_LEN(msg->length)); + msg = (struct webmsg *) ((char *) msg + WEBMSG_LEN(msg->length)); } - /** @todo Implement */ return 0; } @@ -362,100 +261,42 @@ int protocol_cb_live(struct lws *wsi, enum lws_callback_reasons reason, void *us } } -int websocket_init(int argc, char * argv[], config_setting_t *cfg) +int websocket_start(struct node *n) { - config_setting_t *cfg_http; - - lws_set_log_level((1 << LLL_COUNT) - 1, logger); - - /* Parse global config */ - cfg_http = config_setting_lookup(cfg, "http"); - if (cfg_http) { - config_setting_lookup_string(cfg_http, "ssl_cert", &ssl_cert); - config_setting_lookup_string(cfg_http, "ssl_private_key", &ssl_private_key); - config_setting_lookup_string(cfg_http, "htdocs", &htdocs); - config_setting_lookup_int(cfg_http, "port", &port); - } - - /* Default settings */ - if (!port) - port = 80; - if (!htdocs) - htdocs = "/villas/contrib/websocket"; - - /* Start server */ - struct lws_context_creation_info info = { - .port = port, - .protocols = protocols, - .extensions = NULL, //exts, - .ssl_cert_filepath = ssl_cert, - .ssl_private_key_filepath = ssl_private_key, - .gid = -1, - .uid = -1 - }; - - context = lws_create_context(&info); - if (context == NULL) - error("WebSocket: failed to initialize server"); - - /* Save root config for GET /config.json request */ - cfg_root = cfg; - - pthread_create(&thread, NULL, server_thread, NULL); - - return 0; -} - -int websocket_deinit() -{ - lws_cancel_service(context); - lws_context_destroy(context); - - pthread_cancel(thread); - pthread_join(thread, NULL); - - return 0; -} - -int websocket_open(struct node *n) -{ - struct websocket *w = n->_vd; - int ret; + struct websocket *w = n->_vd; + + w->id = id++; list_init(&w->connections); list_init(&w->destinations); - size_t blocklen = LWS_PRE + MSG_LEN(DEFAULT_VALUES); + size_t blocklen = LWS_PRE + WEBMSG_LEN(DEFAULT_VALUES); - ret = pool_init_mmap(&w->pool, blocklen, 2 * DEFAULT_QUEUELEN); + ret = pool_init(&w->pool, 64 * DEFAULT_QUEUELEN, blocklen, &memtype_hugepage); if (ret) return ret; - ret = queue_init(&w->queue_tx, DEFAULT_QUEUELEN); + ret = queue_init(&w->queue, DEFAULT_QUEUELEN, &memtype_hugepage); if (ret) return ret; - - ret = queue_init(&w->queue_rx, DEFAULT_QUEUELEN); - if (ret) - return ret; - - queue_reader_add(&w->queue_rx, 0, 0); - + return 0; } -int websocket_close(struct node *n) +int websocket_stop(struct node *n) { struct websocket *w = n->_vd; - w->shutdown = 1; - - list_foreach(struct lws *wsi, &w->connections) - lws_callback_on_writable(wsi); + for (size_t i = 0; i < list_length(&w->connections); i++) { + struct websocket_connection *c = list_at(&w->connections, i); + + c->state = WEBSOCKET_SHUTDOWN; + lws_callback_on_writable(c->wsi); + } pool_destroy(&w->pool); - queue_destroy(&w->queue_tx); + queue_destroy(&w->queue); list_destroy(&w->connections, NULL, false); @@ -464,7 +305,9 @@ int websocket_close(struct node *n) int websocket_destroy(struct node *n) { -// struct websocket *w = n->_vd; + struct websocket *w = n->_vd; + + list_destroy(&w->destinations, (dtor_cb_t) websocket_destination_destroy, true); return 0; } @@ -473,17 +316,21 @@ int websocket_read(struct node *n, struct sample *smps[], unsigned cnt) { struct websocket *w = n->_vd; - struct msg *msgs[cnt]; + struct webmsg *msgs[cnt]; int got; - got = queue_pull_many(&w->queue_rx, (void **) msgs, cnt, &w->received); + do { + got = queue_pull_many(&w->queue, (void **) msgs, cnt); + pthread_yield(); + } while (got == 0); + for (int i = 0; i < got; i++) { smps[i]->sequence = msgs[i]->sequence; smps[i]->length = msgs[i]->length; - smps[i]->ts.origin = MSG_TS(msgs[i]); + smps[i]->ts.origin = WEBMSG_TS(msgs[i]); - memcpy(&smps[i]->data, &msgs[i]->data, MSG_DATA_LEN(msgs[i]->length)); + memcpy(&smps[i]->data, &msgs[i]->data, WEBMSG_DATA_LEN(msgs[i]->length)); } pool_put_many(&w->pool, (void **) msgs, got); @@ -495,67 +342,102 @@ int websocket_write(struct node *n, struct sample *smps[], unsigned cnt) { struct websocket *w = n->_vd; - int blocks, enqueued; - char *bufs[cnt]; - - /* Copy samples to websocket queue */ - blocks = pool_get_many(&w->pool, (void **) bufs, cnt); - if (blocks != cnt) - warn("Pool underrun in websocket node: %s", node_name(n)); - for (int i = 0; i < blocks; i++) { - struct msg *msg = (struct msg *) (bufs[i] + LWS_PRE); - - msg->version = MSG_VERSION; - msg->type = MSG_TYPE_DATA; - msg->endian = MSG_ENDIAN_HOST; - msg->length = smps[i]->length; - msg->sequence = smps[i]->sequence; - msg->ts.sec = smps[i]->ts.origin.tv_sec; - msg->ts.nsec = smps[i]->ts.origin.tv_nsec; - - memcpy(&msg->data, &smps[i]->data, smps[i]->length * 4); + for (size_t i = 0; i < list_length(&w->connections); i++) { + struct websocket_connection *c = list_at(&w->connections, i); + + websocket_connection_write(c, smps, cnt); } - enqueued = queue_push_many(&w->queue_tx, (void **) bufs, cnt, &w->sent); - if (enqueued != blocks) - warn("Queue overrun in websocket node: %s", node_name(n)); + for (size_t i = 0; i < list_length(&connections); i++) { + struct websocket_connection *c = list_at(&connections, i); - /* Notify all active websocket connections to send new data */ - list_foreach(struct websocket_connection *c, &w->connections) { - switch (c->state) { - case WEBSOCKET_CLOSED: - queue_reader_remove(&w->queue_tx, c->sent, w->sent); - list_remove(&w->connections, c); - break; - - case WEBSOCKET_ESTABLISHED: - c->sent = w->sent; - c->state = WEBSOCKET_ACTIVE; - - queue_reader_add(&w->queue_tx, c->sent, w->sent); - - case WEBSOCKET_ACTIVE: - lws_callback_on_writable(c->wsi); - break; - } + websocket_connection_write(c, smps, cnt); } return cnt; } -static struct node_type vt = { +int websocket_parse(struct node *n, config_setting_t *cfg) +{ + struct websocket *w = n->_vd; + config_setting_t *cfg_dests; + int ret; + + cfg_dests = config_setting_get_member(cfg, "destinations"); + if (cfg_dests) { + if (!config_setting_is_array(cfg_dests)) + cerror(cfg_dests, "The 'destinations' setting must be an array of URLs"); + + for (int i = 0; i < config_setting_length(cfg_dests); i++) { + struct destination *d; + const char *uri, *prot, *ads, *path; + + uri = config_setting_get_string_elem(cfg_dests, i); + if (!uri) + cerror(cfg_dests, "The 'destinations' setting must be an array of URLs"); + + d = alloc(sizeof(struct destination)); + + d->uri = strdup(uri); + if (!d->uri) + serror("Failed to allocate memory"); + + ret = lws_parse_uri(d->uri, &prot, &ads, &d->info.port, &path); + if (ret) + cerror(cfg_dests, "Failed to parse websocket URI: '%s'", uri); + + d->info.ssl_connection = !strcmp(prot, "https"); + d->info.address = ads; + d->info.path = path; + d->info.protocol = prot; + d->info.ietf_version_or_minus_one = -1; + + list_push(&w->destinations, d); + } + } + + return 0; +} + +char * websocket_print(struct node *n) +{ + struct websocket *w = n->_vd; + + char *buf = NULL; + + buf = strcatf(&buf, "dests="); + + for (size_t i = 0; i < list_length(&w->destinations); i++) { + struct lws_client_connect_info *in = list_at(&w->destinations, i); + + buf = strcatf(&buf, "%s://%s:%d/%s", + in->ssl_connection ? "https" : "http", + in->address, + in->port, + in->path + ); + } + + return buf; +} + +static struct plugin p = { .name = "websocket", .description = "Send and receive samples of a WebSocket connection (libwebsockets)", - .vectorize = 0, /* unlimited */ - .size = sizeof(struct websocket), - .open = websocket_open, - .close = websocket_close, - .destroy = websocket_destroy, - .read = websocket_read, - .write = websocket_write, - .init = websocket_init, - .deinit = websocket_deinit + .type = PLUGIN_TYPE_NODE, + .node = { + .vectorize = 0, /* unlimited */ + .size = sizeof(struct websocket), + .start = websocket_start, + .stop = websocket_stop, + .destroy = websocket_destroy, + .read = websocket_read, + .write = websocket_write, + .print = websocket_print, + .parse = websocket_parse, + .instances = LIST_INIT() + } }; -REGISTER_NODE_TYPE(&vt) \ No newline at end of file +REGISTER_PLUGIN(&p) \ No newline at end of file diff --git a/lib/path.c b/lib/path.c index cac77448d..75ccc8f98 100644 --- a/lib/path.c +++ b/lib/path.c @@ -1,7 +1,7 @@ /** Message paths. * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include @@ -9,6 +9,7 @@ #include #include #include +#include #include "config.h" #include "utils.h" @@ -16,227 +17,455 @@ #include "timing.h" #include "pool.h" #include "queue.h" +#include "hook.h" +#include "plugin.h" +#include "super_node.h" +#include "memory.h" -static void path_write(struct path *p, bool resend) +static void path_read(struct path *p) { - list_foreach(struct node *n, &p->destinations) { - int cnt = n->vectorize; - int sent, tosend, available, released; - struct sample *smps[n->vectorize]; + int recv; + int enqueue; + int enqueued; + int ready = 0; /**< Number of blocks in smps[] which are allocated and ready to be used by node_read(). */ + + struct path_source *ps = p->source; + + int cnt = ps->node->vectorize; - available = queue_pull_many(&p->queue, (void **) smps, cnt); - if (available < cnt) - warn("Queue underrun for path %s: available=%u expected=%u", path_name(p), available, cnt); - - if (available == 0) - continue; - - tosend = hook_run(p, smps, available, HOOK_WRITE); - if (tosend == 0) - continue; - - sent = node_write(n, smps, tosend); - if (sent < 0) - error("Failed to sent %u samples to node %s", cnt, node_name(n)); - else if (sent < tosend) - warn("Partial write to node %s", node_name(n)); + struct sample *smps[cnt]; - debug(DBG_PATH | 15, "Sent %u messages to node %s", sent, node_name(n)); + /* Fill smps[] free sample blocks from the pool */ + ready += sample_alloc(&ps->pool, smps, cnt - ready); + if (ready != cnt) + warn("Pool underrun for path %s", path_name(p)); - released = pool_put_many(&p->pool, (void **) smps, sent); - if (sent != released) - warn("Failed to release %u samples to pool for path %s", sent - released, path_name(p)); + /* Read ready samples and store them to blocks pointed by smps[] */ + recv = node_read(ps->node, smps, ready); + if (recv < 0) + error("Failed to receive message from node %s", node_name(ps->node)); + else if (recv < ready) + warn("Partial read for path %s: read=%u expected=%u", path_name(p), recv, ready); + + debug(LOG_PATH | 15, "Received %u messages from node %s", recv, node_name(ps->node)); + + /* Run preprocessing hooks for vector of samples */ + enqueue = path_run_hooks(p, HOOK_READ, smps, recv); + if (enqueue != recv) { + info("Hooks skipped %u out of %u samples for path %s", recv - enqueue, recv, path_name(p)); + + stats_update(p->stats->delta, STATS_SKIPPED, recv - enqueue); + } + + for (size_t i = 0; i < list_length(&p->destinations); i++) { + struct path_destination *pd = list_at(&p->destinations, i); + + enqueued = queue_push_many(&pd->queue, (void **) smps, enqueue); + if (enqueue != enqueued) + warn("Queue overrun for path %s", path_name(p)); + + for (int i = 0; i < enqueued; i++) + sample_get(smps[i]); /* increase reference count */ + + debug(LOG_PATH | 15, "Enqueued %u samples from %s to queue of %s", enqueued, node_name(ps->node), node_name(pd->node)); } } -/** Send messages asynchronously */ -static void * path_run_async(void *arg) +static void path_write(struct path *p) { - struct path *p = arg; + for (size_t i = 0; i < list_length(&p->destinations); i++) { + struct path_destination *pd = list_at(&p->destinations, i); + + int cnt = pd->node->vectorize; + int sent; + int tosend; + int available; + int released; - /* Block until 1/p->rate seconds elapsed */ - for (;;) { - /* Check for overruns */ - uint64_t expir = timerfd_wait(p->tfd); - if (expir == 0) - perror("Failed to wait for timer"); - else if (expir > 1) { - p->overrun += expir; - warn("Overrun detected for path: overruns=%" PRIu64, expir); + struct sample *smps[cnt]; + + /* As long as there are still samples in the queue */ + while (1) { + available = queue_pull_many(&pd->queue, (void **) smps, cnt); + if (available == 0) + break; + else if (available < cnt) + debug(LOG_PATH | 5, "Queue underrun for path %s: available=%u expected=%u", path_name(p), available, cnt); + + debug(LOG_PATH | 15, "Dequeued %u samples from queue of node %s which is part of path %s", available, node_name(pd->node), path_name(p)); + + tosend = path_run_hooks(p, HOOK_WRITE, smps, available); + if (tosend == 0) + continue; + + sent = node_write(pd->node, smps, tosend); + if (sent < 0) + error("Failed to sent %u samples to node %s", cnt, node_name(pd->node)); + else if (sent < tosend) + warn("Partial write to node %s", node_name(pd->node)); + + debug(LOG_PATH | 15, "Sent %u messages to node %s", sent, node_name(pd->node)); + + released = 0; + for (int i = 0; i < sent; i++) { + if (sample_put(smps[i]) == 0) + released++; /* we had the last reference (0 remaining) */ + } + + debug(LOG_PATH | 15, "Released %d samples back to memory pool", released); } - - if (hook_run(p, NULL, 0, HOOK_ASYNC)) - continue; - - path_write(p, true); } - - return NULL; } -/** Receive messages */ +/** Main thread function per path: receive -> sent messages */ static void * path_run(void *arg) { struct path *p = arg; - unsigned cnt = p->in->vectorize; - int recv, enqueue, enqueued; - int ready = 0; /**< Number of blocks in smps[] which are allocated and ready to be used by node_read(). */ - struct sample *smps[cnt]; - /* Main thread loop */ for (;;) { - /* Fill smps[] free sample blocks from the pool */ - ready += sample_get_many(&p->pool, smps, cnt - ready); - if (ready != cnt) - warn("Pool underrun for path %s", path_name(p)); - - /* Read ready samples and store them to blocks pointed by smps[] */ - recv = p->in->_vt->read(p->in, smps, ready); - if (recv < 0) - error("Failed to receive message from node %s", node_name(p->in)); - else if (recv < ready) - warn("Partial read for path %s: read=%u expected=%u", path_name(p), recv, ready); - - debug(DBG_PATH | 15, "Received %u messages from node %s", recv, node_name(p->in)); - - /* Run preprocessing hooks for vector of samples */ - enqueue = hook_run(p, smps, recv, HOOK_READ); - if (enqueue != recv) { - info("Hooks skipped %u out of %u samples for path %s", recv - enqueue, recv, path_name(p)); - p->skipped += recv - enqueue; - } - - enqueued = queue_push_many(&p->queue, (void **) smps, enqueue); - if (enqueue != enqueued) - warn("Failed to enqueue %u samples for path %s", enqueue - enqueued, path_name(p)); - - ready -= enqueued; - - debug(DBG_PATH | 3, "Enqueuing %u samples to queue of path %s", enqueue, path_name(p)); - - /* At fixed rate mode, messages are send by another (asynchronous) thread */ - if (p->rate == 0) - path_write(p, false); + path_read(p); + path_write(p); } return NULL; } +static int path_source_destroy(struct path_source *ps) +{ + pool_destroy(&ps->pool); + + return 0; +} + +static int path_destination_destroy(struct path_destination *pd) +{ + queue_destroy(&pd->queue); + + return 0; +} + +int path_init(struct path *p, struct super_node *sn) +{ + assert(p->state == STATE_DESTROYED); + + list_init(&p->hooks); + list_init(&p->destinations); + + /* Default values */ + p->reverse = 0; + p->enabled = 1; + + p->samplelen = DEFAULT_VALUES; + p->queuelen = DEFAULT_QUEUELEN; + + p->super_node = sn; + + p->state = STATE_INITIALIZED; + + return 0; +} + +int path_parse(struct path *p, config_setting_t *cfg, struct list *nodes) +{ + config_setting_t *cfg_out, *cfg_hooks; + const char *in; + int ret; + + struct node *source; + struct list destinations = { .state = STATE_DESTROYED }; + + list_init(&destinations); + + /* Input node */ + if (!config_setting_lookup_string(cfg, "in", &in) && + !config_setting_lookup_string(cfg, "from", &in) && + !config_setting_lookup_string(cfg, "src", &in) && + !config_setting_lookup_string(cfg, "source", &in)) + cerror(cfg, "Missing input node for path"); + + source = list_lookup(nodes, in); + if (!source) + cerror(cfg, "Invalid input node '%s'", in); + + /* Output node(s) */ + if (!(cfg_out = config_setting_get_member(cfg, "out")) && + !(cfg_out = config_setting_get_member(cfg, "to")) && + !(cfg_out = config_setting_get_member(cfg, "dst")) && + !(cfg_out = config_setting_get_member(cfg, "dest")) && + !(cfg_out = config_setting_get_member(cfg, "sink"))) + cerror(cfg, "Missing output nodes for path"); + + ret = node_parse_list(&destinations, cfg_out, nodes); + if (ret || list_length(&destinations) == 0) + cerror(cfg_out, "Invalid output nodes"); + + /* Optional settings */ + cfg_hooks = config_setting_get_member(cfg, "hooks"); + if (cfg_hooks) { + ret = hook_parse_list(&p->hooks, cfg_hooks, p); + if (ret) + return ret; + } + + config_setting_lookup_bool(cfg, "reverse", &p->reverse); + config_setting_lookup_bool(cfg, "enabled", &p->enabled); + config_setting_lookup_int(cfg, "values", &p->samplelen); + config_setting_lookup_int(cfg, "queuelen", &p->queuelen); + + if (!IS_POW2(p->queuelen)) { + p->queuelen = LOG2_CEIL(p->queuelen); + warn("Queue length should always be a power of 2. Adjusting to %d", p->queuelen); + } + + p->cfg = cfg; + + p->source = alloc(sizeof(struct path_source)); + p->source->node = source; + p->source->samplelen = p->samplelen; + + for (size_t i = 0; i < list_length(&destinations); i++) { + struct node *n = list_at(&destinations, i); + + struct path_destination pd = { + .node = n, + .queuelen = p->queuelen + }; + + list_push(&p->destinations, memdup(&pd, sizeof(pd))); + } + + list_destroy(&destinations, NULL, false); + + return 0; +} + +int path_check(struct path *p) +{ + assert(p->state != STATE_DESTROYED); + + for (size_t i = 0; i < list_length(&p->destinations); i++) { + struct path_destination *pd = list_at(&p->destinations, i); + + if (!pd->node->_vt->write) + error("Destiation node '%s' is not supported as a sink for path '%s'", node_name(pd->node), path_name(p)); + } + + if (!p->source->node->_vt->read) + error("Source node '%s' is not supported as source for path '%s'", node_name(p->source->node), path_name(p)); + + p->state = STATE_CHECKED; + + return 0; +} + +int path_init2(struct path *p) +{ + int ret, max_queuelen = 0; + + assert(p->state == STATE_CHECKED); + + /* Add internal hooks if they are not already in the list*/ + for (size_t i = 0; i < list_length(&plugins); i++) { + struct plugin *q = list_at(&plugins, i); + + if (q->type == PLUGIN_TYPE_HOOK) { + struct hook h; + struct hook_type *vt = &q->hook; + + if (vt->when & HOOK_AUTO) { + hook_init(&h, vt, p->super_node); + + list_push(&p->hooks, memdup(&h, sizeof(h))); + } + } + } + + /* We sort the hooks according to their priority before starting the path */ + list_sort(&p->hooks, hook_cmp_priority); + + /* Initialize destinations */ + for (size_t i = 0; i < list_length(&p->destinations); i++) { + struct path_destination *pd = list_at(&p->destinations, i); + + ret = queue_init(&pd->queue, pd->queuelen, &memtype_hugepage); + if (ret) + error("Failed to initialize queue for path"); + + if (pd->queuelen > max_queuelen) + max_queuelen = pd->queuelen; + } + + /* Initialize source */ + ret = pool_init(&p->source->pool, max_queuelen, SAMPLE_LEN(p->source->samplelen), &memtype_hugepage); + if (ret) + error("Failed to allocate memory pool for path"); + + return 0; +} + int path_start(struct path *p) { int ret; - - info("Starting path: %s (#hooks=%zu, rate=%.1f)", - path_name(p), list_length(&p->hooks), p->rate); - - ret = hook_run(p, NULL, 0, HOOK_PATH_START); - if (ret) - return -1; - - /* At fixed rate mode, we start another thread for sending */ - if (p->rate) { - p->tfd = timerfd_create_rate(p->rate); - if (p->tfd < 0) - serror("Failed to create timer"); - - pthread_create(&p->sent_tid, NULL, &path_run_async, p); - } - p->state = PATH_RUNNING; + assert(p->state == STATE_CHECKED); - return pthread_create(&p->recv_tid, NULL, &path_run, p); + info("Starting path: %s (#hooks=%zu)", path_name(p), list_length(&p->hooks)); + + for (size_t i = 0; i < list_length(&p->hooks); i++) { + struct hook *h = list_at(&p->hooks, i); + + if (ret) + return ret; + } + + /* Start one thread per path for sending to destinations */ + ret = pthread_create(&p->tid, NULL, &path_run, p); + if (ret) + return ret; + + p->state = STATE_STARTED; + + return 0; } + int path_stop(struct path *p) { + int ret; + info("Stopping path: %s", path_name(p)); - pthread_cancel(p->recv_tid); - pthread_join(p->recv_tid, NULL); + pthread_cancel(p->tid); + pthread_join(p->tid, NULL); - if (p->rate) { - pthread_cancel(p->sent_tid); - pthread_join(p->sent_tid, NULL); + for (size_t i = 0; i < list_length(&p->hooks); i++) { + struct hook *h = list_at(&p->hooks, i); - close(p->tfd); + ret = hook_run(h, HOOK_STOP, NULL, 0); + if (ret) + return ret; } + + p->state = STATE_STOPPED; + + return 0; +} + +int path_destroy(struct path *p) +{ + list_destroy(&p->hooks, (dtor_cb_t) hook_destroy, true); + list_destroy(&p->destinations, (dtor_cb_t) path_destination_destroy, true); - p->state = PATH_STOPPED; + path_source_destroy(p->source); - if (hook_run(p, NULL, 0, HOOK_PATH_STOP)) - return -1; + if (p->_name) + free(p->_name); + if (p->source) + free(p->source); + + p->state = STATE_DESTROYED; + return 0; } const char * path_name(struct path *p) { - if (!p->_name) { - strcatf(&p->_name, "%s " MAG("=>"), node_name_short(p->in)); + if (!p->_name) { + if (list_length(&p->destinations) == 1) { + struct path_destination *pd = (struct path_destination *) list_first(&p->destinations); + + strcatf(&p->_name, "%s " MAG("=>") " %s", + node_name_short(p->source->node), + node_name_short(pd->node)); + } + else { + strcatf(&p->_name, "%s " MAG("=>") " [", node_name_short(p->source->node)); + + for (size_t i = 0; i < list_length(&p->destinations); i++) { + struct path_destination *pd = list_at(&p->destinations, i); - list_foreach(struct node *n, &p->destinations) - strcatf(&p->_name, " %s", node_name_short(n)); + strcatf(&p->_name, " %s", node_name_short(pd->node)); + } + + strcatf(&p->_name, " ]"); + } } return p->_name; } -void path_init(struct path *p) -{ - list_init(&p->destinations); - list_init(&p->hooks); - - /* Initialize hook system */ - list_foreach(struct hook *h, &hooks) { - if (h->type & HOOK_INTERNAL) - list_push(&p->hooks, memdup(h, sizeof(*h))); +int path_uses_node(struct path *p, struct node *n) { + for (size_t i = 0; i < list_length(&p->destinations); i++) { + struct path_destination *pd = list_at(&p->destinations, i); + + if (pd->node == n) + return 0; } - p->state = PATH_CREATED; + return p->source->node == n ? 0 : -1; } -int path_prepare(struct path *p) +int path_reverse(struct path *p, struct path *r) { int ret; + + if (list_length(&p->destinations) > 1) + return -1; - /* We sort the hooks according to their priority before starting the path */ - list_sort(&p->hooks, hooks_sort_priority); + struct path_destination *first_pd = list_first(&p->destinations); - /* Allocate hook private memory */ - ret = hook_run(p, NULL, 0, HOOK_INIT); - if (ret) - error("Failed to initialize hooks of path: %s", path_name(p)); - - /* Parse hook arguments */ - ret = hook_run(p, NULL, 0, HOOK_PARSE); - if (ret) - error("Failed to parse arguments for hooks of path: %s", path_name(p)); - - /* Initialize queue */ - ret = pool_init(&p->pool, SAMPLE_LEN(p->samplelen), p->queuelen, &memtype_hugepage); - if (ret) - error("Failed to allocate memory pool for path"); + /* General */ + r->enabled = p->enabled; + r->cfg = p->cfg; - ret = queue_init(&p->queue, p->queuelen, &memtype_hugepage); - if (ret) - error("Failed to initialize queue for path"); + struct path_destination *pd = alloc(sizeof(struct path_destination)); + + pd->node = p->source->node; + pd->queuelen = first_pd->queuelen; + list_push(&r->destinations, pd); + + struct path_source *ps = alloc(sizeof(struct path_source)); + + ps->node = first_pd->node; + ps->samplelen = p->source->samplelen; + + r->source = ps; + + for (size_t i = 0; i < list_length(&p->hooks); i++) { + struct hook *h = list_at(&p->hooks, i); + struct hook hc; + + ret = hook_init(&hc, h->_vt, p); + if (ret) + return ret; + + list_push(&r->hooks, memdup(&hc, sizeof(hc))); + } + return 0; } -void path_destroy(struct path *p) +int path_run_hooks(struct path *p, int when, struct sample *smps[], size_t cnt) { - hook_run(p, NULL, 0, HOOK_DEINIT); /* Release memory */ + int ret = 0; - list_destroy(&p->destinations, NULL, false); - list_destroy(&p->hooks, NULL, true); - - queue_destroy(&p->queue); - pool_destroy(&p->pool); + struct hook_info i = { + .samples = smps, + .count = cnt + }; - free(p->_name); -} + if (ret) + break; + + if (i.count == 0) + for (size_t i = 0; i < list_length(&p->hooks); i++) { + struct hook *h = list_at(&p->hooks, i); -int path_uses_node(struct path *p, struct node *n) { - return (p->in == n) || list_contains(&p->destinations, n) ? 0 : 1; -} + ret = hook_run(h, when, smps, &cnt); + break; + } + + return i.count; +} \ No newline at end of file diff --git a/lib/plugin.c b/lib/plugin.c new file mode 100644 index 000000000..4aab33115 --- /dev/null +++ b/lib/plugin.c @@ -0,0 +1,90 @@ +/** Loadable / plugin support. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#include + +#include "plugin.h" + +/** Global list of all known plugins */ +struct list plugins = LIST_INIT(); + +int plugin_init(struct plugin *p) +{ + assert(p->state == STATE_DESTROYED); + + p->state = STATE_INITIALIZED; + + return 0; +} + +int plugin_parse(struct plugin *p, config_setting_t *cfg) +{ + const char *path; + + path = config_setting_get_string(cfg); + if (!path) + cerror(cfg, "Setting 'plugin' must be a string."); + + return 0; +} + +int plugin_load(struct plugin *p) +{ + p->handle = dlopen(p->path, RTLD_NOW); + if (!p->path) + return -1; + + p->state = STATE_LOADED; + + return 0; +} + +int plugin_unload(struct plugin *p) +{ + int ret; + + assert(p->state == STATE_LOADED); + + ret = dlclose(p->handle); + if (ret) + return -1; + + p->state = STATE_UNLOADED; + + return 0; +} + +int plugin_destroy(struct plugin *p) +{ + assert(p->state != STATE_DESTROYED && p->state != STATE_LOADED); + + if (p->path) + free(p->path); + + return 0; +} + +struct plugin * plugin_lookup(enum plugin_type type, const char *name) +{ + for (size_t i = 0; i < list_length(&plugins); i++) { + struct plugin *p = list_at(&plugins, i); + + if (p->type == type && strcmp(p->name, name) == 0) + return p; + } + + return NULL; +} + +void plugin_dump(enum plugin_type type) +{ + for (size_t i = 0; i < list_length(&plugins); i++) { + struct plugin *p = list_at(&plugins, i); + + if (p->type == type) + printf(" - %-12s: %s\n", p->name, p->description); + } +} diff --git a/lib/pool.c b/lib/pool.c index 7d6e0ef56..e2398d875 100644 --- a/lib/pool.c +++ b/lib/pool.c @@ -1,8 +1,8 @@ /** Memory pool for fixed size objects. * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC - */ + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ #include "utils.h" @@ -13,10 +13,12 @@ int pool_init(struct pool *p, size_t cnt, size_t blocksz, const struct memtype *m) { int ret; + + assert(p->state == STATE_DESTROYED); /* Make sure that we use a block size that is aligned to the size of a cache line */ p->alignment = kernel_get_cacheline_size(); - p->blocksz = blocksz * CEIL(blocksz, p->alignment); + p->blocksz = p->alignment * CEIL(blocksz, p->alignment); p->len = cnt * p->blocksz; p->mem = m; @@ -24,21 +26,31 @@ int pool_init(struct pool *p, size_t cnt, size_t blocksz, const struct memtype * if (!p->buffer) serror("Failed to allocate memory for memory pool"); else - debug(DBG_POOL | 4, "Allocated %#zx bytes for memory pool", p->len); + debug(LOG_POOL | 4, "Allocated %#zx bytes for memory pool", p->len); - ret = queue_init(&p->queue, cnt, m); + ret = queue_init(&p->queue, LOG2_CEIL(cnt), m); if (ret) return ret; for (int i = 0; i < cnt; i++) queue_push(&p->queue, (char *) p->buffer + i * p->blocksz); + + p->state = STATE_INITIALIZED; return 0; } int pool_destroy(struct pool *p) { + int ret; + + assert(p->state == STATE_INITIALIZED); + queue_destroy(&p->queue); - return memory_free(p->mem, p->buffer, p->len); + ret = memory_free(p->mem, p->buffer, p->len); + if (ret == 0) + p->state = STATE_DESTROYED; + + return ret; } \ No newline at end of file diff --git a/lib/queue.c b/lib/queue.c index 20a7a6710..10ef9ec3e 100644 --- a/lib/queue.c +++ b/lib/queue.c @@ -4,7 +4,7 @@ * http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue * * @author Steffen Vogel - * @copyright 2016 Steffen Vogel + * @copyright 2017 Steffen Vogel * @license BSD 2-Clause License * * All rights reserved. @@ -29,15 +29,17 @@ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ + *********************************************************************************/ #include "queue.h" #include "utils.h" +#include "memory.h" /** Initialize MPMC queue */ int queue_init(struct queue *q, size_t size, const struct memtype *mem) { - + assert(q->state == STATE_DESTROYED); + /* Queue size must be 2 exponent */ if (!IS_POW2(size)) { size_t old_size = size; @@ -57,12 +59,23 @@ int queue_init(struct queue *q, size_t size, const struct memtype *mem) atomic_store_explicit(&q->tail, 0, memory_order_relaxed); atomic_store_explicit(&q->head, 0, memory_order_relaxed); + q->state = STATE_INITIALIZED; + return 0; } int queue_destroy(struct queue *q) { - return memory_free(q->mem, q->buffer, (q->buffer_mask + 1) * sizeof(q->buffer[0])); + int ret = 0; + + assert(q->state == STATE_INITIALIZED); + + ret = memory_free(q->mem, q->buffer, (q->buffer_mask + 1) * sizeof(q->buffer[0])); + + if (ret == 0) + q->state = STATE_DESTROYED; + + return ret; } /** Return estimation of current queue usage. diff --git a/lib/sample.c b/lib/sample.c index 1e13c9b74..331a776cf 100644 --- a/lib/sample.c +++ b/lib/sample.c @@ -1,28 +1,35 @@ /** The internal datastructure for a sample of simulation data. * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ -#include - #include "pool.h" #include "sample.h" -#include "timing.h" -int sample_get_many(struct pool *p, struct sample *smps[], int cnt) { +int sample_alloc(struct pool *p, struct sample *smps[], int cnt) +{ int ret; ret = pool_get_many(p, (void **) smps, cnt); if (ret < 0) return ret; - for (int i = 0; i < ret; i++) + for (int i = 0; i < ret; i++) { smps[i]->capacity = (p->blocksz - sizeof(**smps)) / sizeof(smps[0]->data[0]); + smps[i]->pool = p; + smps[i]->format = 0; /* all sample values are float by default */ + } return ret; } +void sample_free(struct sample *smps[], int cnt) +{ + for (int i = 0; i < cnt; i++) + pool_put(smps[i]->pool, smps[i]); +} + int sample_get(struct sample *s) { return atomic_fetch_add(&s->refcnt, 1) + 1; @@ -39,130 +46,23 @@ int sample_put(struct sample *s) return prev - 1; } -int sample_print(char *buf, size_t len, struct sample *s, int flags) +int sample_set_data_format(struct sample *s, int idx, enum sample_data_format fmt) { - size_t off = snprintf(buf, len, "%llu", (unsigned long long) s->ts.origin.tv_sec); + if (idx >= sizeof(s->format) * 8) + return 0; /* we currently can only control the format of the first 64 values. */ - if (flags & SAMPLE_NANOSECONDS) - off += snprintf(buf + off, len - off, ".%09llu", (unsigned long long) s->ts.origin.tv_nsec); - - if (flags & SAMPLE_OFFSET) - off += snprintf(buf + off, len - off, "%+e", time_delta(&s->ts.origin, &s->ts.received)); - - if (flags & SAMPLE_SEQUENCE) - off += snprintf(buf + off, len - off, "(%u)", s->sequence); - - if (flags & SAMPLE_VALUES) { - for (int i = 0; i < s->length; i++) - off += snprintf(buf + off, len - off, "\t%.6f", s->data[i].f); + switch (fmt) { + case SAMPLE_DATA_FORMAT_FLOAT: s->format &= ~(1 << idx); break; + case SAMPLE_DATA_FORMAT_INT: s->format |= (fmt << idx); break; } - - off += snprintf(buf + off, len - off, "\n"); - - return off + 1; /* trailing '\0' */ + + return 0; } -int sample_scan(const char *line, struct sample *s, int *fl) +int sample_get_data_format(struct sample *s, int idx) { - char *end; - const char *ptr = line; - - int flags = 0; - double offset = 0; - - /* Format: Seconds.NanoSeconds+Offset(SequenceNumber) Value1 Value2 ... - * RegEx: (\d+(?:\.\d+)?)([-+]\d+(?:\.\d+)?(?:e[+-]?\d+)?)?(?:\((\d+)\))? - * - * Please note that only the seconds and at least one value are mandatory - */ - - /* Mandatory: seconds */ - s->ts.origin.tv_sec = (uint32_t) strtoul(ptr, &end, 10); - if (ptr == end) - return -2; - - /* Optional: nano seconds */ - if (*end == '.') { - ptr = end + 1; - - s->ts.origin.tv_nsec = (uint32_t) strtoul(ptr, &end, 10); - if (ptr != end) - flags |= SAMPLE_NANOSECONDS; - else - return -3; - } - else - s->ts.origin.tv_nsec = 0; - - /* Optional: offset / delay */ - if (*end == '+' || *end == '-') { - ptr = end; - - offset = strtof(ptr, &end); /* offset is ignored for now */ - if (ptr != end) - flags |= SAMPLE_OFFSET; - else - return -4; - } + if (idx >= sizeof(s->format) * 8) + return -1; /* we currently can only control the format of the first 64 values. */ - /* Optional: sequence */ - if (*end == '(') { - ptr = end + 1; - - s->sequence = strtoul(ptr, &end, 10); - if (ptr != end) - flags |= SAMPLE_SEQUENCE; - else - return -5; - - if (*end == ')') - end++; - } - - for (ptr = end, s->length = 0; - s->length < s->capacity; - ptr = end, s->length++) { - - s->data[s->length].f = strtod(ptr, &end); /** @todo We only support floating point values at the moment */ - if (end == ptr) /* There are no valid FP values anymore */ - break; - } - - if (s->length > 0) - flags |= SAMPLE_VALUES; - - if (fl) - *fl = flags; - if (flags & SAMPLE_OFFSET) { - struct timespec off = time_from_double(offset); - s->ts.received = time_diff(&s->ts.origin, &off); - } - - return s->length; -} - -int sample_fprint(FILE *f, struct sample *s, int flags) -{ - char line[4096]; - - int len = sample_print(line, sizeof(line), s, flags); - - fputs(line, f); - - return len; -} - -int sample_fscan(FILE *f, struct sample *s, int *fl) -{ - char *ptr, line[4096]; - -skip: if (fgets(line, sizeof(line), f) == NULL) - return -1; /* An error occured */ - - /* Skip whitespaces, empty and comment lines */ - for (ptr = line; isspace(*ptr); ptr++); - if (*ptr == '\0' || *ptr == '#') - goto skip; - - return sample_scan(line, s, fl); + return (s->format >> idx) & 0x1; } \ No newline at end of file diff --git a/lib/sample_io.c b/lib/sample_io.c new file mode 100644 index 000000000..ccd1e871a --- /dev/null +++ b/lib/sample_io.c @@ -0,0 +1,282 @@ +/** The internal datastructure for a sample of simulation data. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#include + +#include "sample.h" +#include "sample_io.h" +#include "timing.h" + +int sample_io_fprint(FILE *f, struct sample *s, enum sample_io_format fmt, int flags) +{ + switch (fmt) { + case SAMPLE_IO_FORMAT_VILLAS: return sample_io_villas_fprint(f, s, flags); + case SAMPLE_IO_FORMAT_JSON: return sample_io_json_fprint(f, s, flags); + default: + return -1; + } +} + +int sample_io_fscan(FILE *f, struct sample *s, enum sample_io_format fmt, int *flags) +{ + switch (fmt) { + case SAMPLE_IO_FORMAT_VILLAS: return sample_io_villas_fscan(f, s, flags); + case SAMPLE_IO_FORMAT_JSON: return sample_io_json_fscan(f, s, flags); + default: + return -1; + } +} + +int sample_io_villas_print(char *buf, size_t len, struct sample *s, int flags) +{ + size_t off = snprintf(buf, len, "%llu", (unsigned long long) s->ts.origin.tv_sec); + + if (flags & SAMPLE_IO_NANOSECONDS) + off += snprintf(buf + off, len - off, ".%09llu", (unsigned long long) s->ts.origin.tv_nsec); + + if (flags & SAMPLE_IO_OFFSET) + off += snprintf(buf + off, len - off, "%+e", time_delta(&s->ts.origin, &s->ts.received)); + + if (flags & SAMPLE_IO_SEQUENCE) + off += snprintf(buf + off, len - off, "(%u)", s->sequence); + + if (flags & SAMPLE_IO_VALUES) { + for (int i = 0; i < s->length; i++) { + switch ((s->format >> i) & 0x1) { + case SAMPLE_DATA_FORMAT_FLOAT: + off += snprintf(buf + off, len - off, "\t%.6f", s->data[i].f); + break; + case SAMPLE_DATA_FORMAT_INT: + off += snprintf(buf + off, len - off, "\t%d", s->data[i].i); + break; + } + } + } + + off += snprintf(buf + off, len - off, "\n"); + + return 0; /* trailing '\0' */ +} + +int sample_io_villas_scan(const char *line, struct sample *s, int *fl) +{ + char *end; + const char *ptr = line; + + int flags = 0; + double offset = 0; + + /* Format: Seconds.NanoSeconds+Offset(SequenceNumber) Value1 Value2 ... + * RegEx: (\d+(?:\.\d+)?)([-+]\d+(?:\.\d+)?(?:e[+-]?\d+)?)?(?:\((\d+)\))? + * + * Please note that only the seconds and at least one value are mandatory + */ + + /* Mandatory: seconds */ + s->ts.origin.tv_sec = (uint32_t) strtoul(ptr, &end, 10); + if (ptr == end) + return -2; + + /* Optional: nano seconds */ + if (*end == '.') { + ptr = end + 1; + + s->ts.origin.tv_nsec = (uint32_t) strtoul(ptr, &end, 10); + if (ptr != end) + flags |= SAMPLE_IO_NANOSECONDS; + else + return -3; + } + else + s->ts.origin.tv_nsec = 0; + + /* Optional: offset / delay */ + if (*end == '+' || *end == '-') { + ptr = end; + + offset = strtof(ptr, &end); /* offset is ignored for now */ + if (ptr != end) + flags |= SAMPLE_IO_OFFSET; + else + return -4; + } + + /* Optional: sequence */ + if (*end == '(') { + ptr = end + 1; + + s->sequence = strtoul(ptr, &end, 10); + if (ptr != end) + flags |= SAMPLE_IO_SEQUENCE; + else + return -5; + + if (*end == ')') + end++; + } + + for (ptr = end, s->length = 0; + s->length < s->capacity; + ptr = end, s->length++) { + + switch (s->format & (1 << s->length)) { + case SAMPLE_DATA_FORMAT_FLOAT: + s->data[s->length].f = strtod(ptr, &end); + break; + case SAMPLE_DATA_FORMAT_INT: + s->data[s->length].i = strtol(ptr, &end, 10); + break; + } + + if (end == ptr) /* There are no valid FP values anymore */ + break; + } + + if (s->length > 0) + flags |= SAMPLE_IO_VALUES; + + if (fl) + *fl = flags; + if (flags & SAMPLE_IO_OFFSET) { + struct timespec off = time_from_double(offset); + s->ts.received = time_add(&s->ts.origin, &off); + } + else + s->ts.received = s->ts.origin; + + return 0; +} + +int sample_io_villas_fprint(FILE *f, struct sample *s, int flags) +{ + char line[4096]; + int ret; + + ret = sample_io_villas_print(line, sizeof(line), s, flags); + if (ret) + return ret; + + fputs(line, f); + + return 0; +} + +int sample_io_villas_fscan(FILE *f, struct sample *s, int *fl) +{ + char *ptr, line[4096]; + +skip: if (fgets(line, sizeof(line), f) == NULL) + return -1; /* An error occured */ + + /* Skip whitespaces, empty and comment lines */ + for (ptr = line; isspace(*ptr); ptr++); + if (*ptr == '\0' || *ptr == '#') + goto skip; + + return sample_io_villas_scan(line, s, fl); +} + +#ifdef WITH_JANSSON +int sample_io_json_pack(json_t **j, struct sample *s, int flags) +{ + json_error_t err; + json_t *json_data = json_array(); + + for (int i = 0; i < s->length; i++) { + json_t *json_value = sample_get_data_format(s, i) + ? json_integer(s->data[i].i) + : json_real(s->data[i].f); + + json_array_append(json_data, json_value); + } + + *j = json_pack_ex(&err, 0, "{ s: { s: [ I, I ], s: [ I, I ], s: [ I, I ] }, s: I, s: o }", + "ts", + "origin", s->ts.origin.tv_sec, s->ts.origin.tv_nsec, + "received", s->ts.received.tv_sec, s->ts.received.tv_nsec, + "sent", s->ts.sent.tv_sec, s->ts.sent.tv_nsec, + "sequence", s->sequence, + "data", json_data); + + if (!*j) + return -1; + + return 0; +} + +int sample_io_json_unpack(json_t *j, struct sample *s, int *flags) +{ + int ret, i; + json_t *json_data, *json_value; + + ret = json_unpack(j, "{ s: { s: [ I, I ], s: [ I, I ], s: [ I, I ] }, s: I, s: o }", + "ts", + "origin", &s->ts.origin.tv_sec, &s->ts.origin.tv_nsec, + "received", &s->ts.received.tv_sec, &s->ts.received.tv_nsec, + "sent", &s->ts.sent.tv_sec, &s->ts.sent.tv_nsec, + "sequence", &s->sequence, + "data", &json_data); + + if (ret) + return ret; + + s->length = 0; + + json_array_foreach(json_data, i, json_value) { + switch (json_typeof(json_value)) { + case JSON_REAL: + s->data[i].f = json_real_value(json_value); + sample_set_data_format(s, i, SAMPLE_DATA_FORMAT_FLOAT); + break; + + case JSON_INTEGER: + s->data[i].f = json_integer_value(json_value); + sample_set_data_format(s, i, SAMPLE_DATA_FORMAT_INT); + break; + + default: + return -1; + } + + s->length++; + } + + return 0; +} + +int sample_io_json_fprint(FILE *f, struct sample *s, int flags) +{ + int ret; + json_t *json; + + ret = sample_io_json_pack(&json, s, flags); + if (ret) + return ret; + + ret = json_dumpf(json, f, 0); + + json_decref(json); + + return ret; +} + +int sample_io_json_fscan(FILE *f, struct sample *s, int *flags) +{ + int ret; + json_t *json; + json_error_t err; + + json = json_loadf(f, JSON_DISABLE_EOF_CHECK, &err); + if (!json) + return -1; + + ret = sample_io_json_unpack(json, s, flags); + + json_decref(json); + + return ret; +} +#endif \ No newline at end of file diff --git a/lib/stats.c b/lib/stats.c new file mode 100644 index 000000000..7368b7668 --- /dev/null +++ b/lib/stats.c @@ -0,0 +1,212 @@ +/** Statistic collection. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#include "stats.h" +#include "hist.h" +#include "timing.h" +#include "path.h" +#include "sample.h" +#include "utils.h" +#include "log.h" + +static struct stats_desc { + const char *name; + const char *unit; + const char *desc; + struct { + double min; + double max; + double resolution; + } hist; +} stats_table[] = { + { "skipped", "samples", "skipped samples by hooks", {0, 0, -1, }}, + { "dropped", "samples", "dropped messages because of reordering", {0, 0, -1, }}, + { "gap_sequence", "samples", "sequence number displacement of received messages", {-10, 10, 20, }}, + { "gap_sample", "seconds", "inter message timestamps (as sent by remote)", {90e-3, 110e-3, 1e-3, }}, + { "gap_received", "seconds", "Histogram for inter message arrival time (as seen by this instance)", {90e-3, 110e-3, 1e-3, }}, + { "owd", "seconds", "Histogram for one-way-delay (OWD) of received messages", {0, 1, 100e-3, }} +}; + +int stats_init(struct stats *s) +{ + for (int i = 0; i < STATS_COUNT; i++) { + struct stats_desc *desc = &stats_table[i]; + hist_init(&s->histograms[i], desc->hist.min, desc->hist.max, desc->hist.resolution); + } + + s->delta = alloc(sizeof(struct stats_delta)); + + return 0; +} + +void stats_destroy(struct stats *s) +{ + for (int i = 0; i < STATS_COUNT; i++) { + hist_destroy(&s->histograms[i]); + } + + free(s->delta); +} + +void stats_update(struct stats_delta *d, enum stats_id id, double val) +{ + assert(id >= 0 && id < STATS_COUNT); + + d->values[id] = val; + d->update |= 1 << id; +} + +int stats_commit(struct stats *s, struct stats_delta *d) +{ + for (int i = 0; i < STATS_COUNT; i++) { + if (d->update & 1 << i) + hist_put(&s->histograms[i], d->values[i]); + } + + return 0; +} + +void stats_collect(struct stats_delta *s, struct sample *smps[], size_t cnt) +{ + struct sample *previous = s->last; + + for (int i = 0; i < cnt; i++) { + if (previous) { + stats_update(s, STATS_GAP_RECEIVED, time_delta(&previous->ts.received, &smps[i]->ts.received)); + stats_update(s, STATS_GAP_SAMPLE, time_delta(&previous->ts.origin, &smps[i]->ts.origin)); + stats_update(s, STATS_OWD, time_delta(&smps[i]->ts.origin, &smps[i]->ts.received)); + stats_update(s, STATS_GAP_SEQUENCE, smps[i]->sequence - (int32_t) previous->sequence); + } + + previous = smps[i]; + } + + if (s->last) + sample_put(s->last); + + if (previous) + sample_get(previous); + + s->last = previous; +} + +#ifdef WITH_JANSSON +json_t * stats_json(struct stats *s) +{ + json_t *obj = json_object(); + + for (int i = 0; i < STATS_COUNT; i++) { + struct stats_desc *desc = &stats_table[i]; + + json_t *stats = hist_json(&s->histograms[i]); + + json_object_set(obj, desc->name, stats); + } + + return obj; +} + +json_t * stats_json_periodic(struct stats *s, struct path *p) +{ + return json_pack("{ s: s, s: f, s: f, s: i, s: i }" + "path", path_name(p), + "owd", s->histograms[STATS_OWD].last, + "rate", 1.0 / s->histograms[STATS_GAP_SAMPLE].last, + "dropped", s->histograms[STATS_REORDERED].total, + "skipped", s->histograms[STATS_SKIPPED].total + ); +} +#endif + +void stats_reset(struct stats *s) +{ + for (int i = 0; i < STATS_COUNT; i++) { + hist_reset(&s->histograms[i]); + } +} + +void stats_print_header(enum stats_format fmt) +{ + #define UNIT(u) "(" YEL(u) ")" + + switch (fmt) { + case STATS_FORMAT_HUMAN: + stats("%-40s|%19s|%19s|%19s|%19s|", "Source " MAG("=>") " Destination", + "OWD" UNIT("S") " ", + "Rate" UNIT("p/S") " ", + "Drop" UNIT("p") " ", + "Skip" UNIT("p") " " + ); + line(); + break; + + default: { } + } +} + +void stats_print_periodic(struct stats *s, FILE *f, enum stats_format fmt, int verbose, struct path *p) +{ + switch (fmt) { + case STATS_FORMAT_HUMAN: + stats("%-40.40s|%10f|%10f|%10ju|%10ju|", path_name(p), + s->histograms[STATS_OWD].last, + 1.0 / s->histograms[STATS_GAP_SAMPLE].last, + s->histograms[STATS_REORDERED].total, + s->histograms[STATS_SKIPPED].total + ); + break; + + case STATS_FORMAT_JSON: { + json_t *json_stats = stats_json_periodic(s, p); + json_dumpf(json_stats, f, 0); + break; + } + + default: { } + } +} + +void stats_print(struct stats *s, FILE *f, enum stats_format fmt, int verbose) +{ + switch (fmt) { + case STATS_FORMAT_HUMAN: + for (int i = 0; i < STATS_COUNT; i++) { + struct stats_desc *desc = &stats_table[i]; + + stats("%s: %s", desc->name, desc->desc); + hist_print(&s->histograms[i], verbose); + } + break; + + case STATS_FORMAT_JSON: { + json_t *json_stats = stats_json(s); + json_dumpf(json_stats, f, 0); + fflush(f); + break; + } + + default: { } + } +} + +void stats_send(struct stats *s, struct node *n) +{ + char buf[SAMPLE_LEN(STATS_COUNT * 5)]; + struct sample *smp = (struct sample *) buf; + + int i = 0; + + for (int j = 0; j < STATS_COUNT; j++) { + smp->data[i++].f = s->histograms[j].last; + smp->data[i++].f = s->histograms[j].highest; + smp->data[i++].f = s->histograms[j].lowest; + smp->data[i++].f = hist_mean(&s->histograms[j]); + smp->data[i++].f = hist_var(&s->histograms[j]); + } + smp->length = i; + + node_write(n, &smp, 1); /* Send single message with statistics to destination node */ +} \ No newline at end of file diff --git a/lib/super_node.c b/lib/super_node.c new file mode 100644 index 000000000..ee9546a4d --- /dev/null +++ b/lib/super_node.c @@ -0,0 +1,393 @@ +/** Configuration parser. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#include +#include +#include +#include + +#include "super_node.h" +#include "node.h" +#include "path.h" +#include "utils.h" +#include "list.h" +#include "hook.h" +#include "advio.h" +#include "web.h" +#include "log.h" +#include "api.h" +#include "plugin.h" +#include "memory.h" + +#include "kernel/rt.h" + +static void config_dtor(void *data) +{ + if (data) + free(data); +} + +static int super_node_parse_global(struct super_node *sn, config_setting_t *cfg) +{ + if (!config_setting_is_group(cfg)) + cerror(cfg, "Global section must be a dictionary."); + + config_setting_lookup_int(cfg, "hugepages", &sn->hugepages); + config_setting_lookup_int(cfg, "affinity", &sn->affinity); + config_setting_lookup_int(cfg, "priority", &sn->priority); + config_setting_lookup_float(cfg, "stats", &sn->stats); + + return 0; +} + +int super_node_init(struct super_node *sn) +{ + assert(sn->state == STATE_DESTROYED); + + config_init(&sn->cfg); + + log_init(&sn->log, V, LOG_ALL); + api_init(&sn->api, sn); + web_init(&sn->web, &sn->api); + + list_init(&sn->nodes); + list_init(&sn->paths); + list_init(&sn->plugins); + + /* Default values */ + sn->affinity = 0; + sn->priority = 0; + sn->stats = 0; + sn->hugepages = DEFAULT_NR_HUGEPAGES; + + sn->state = STATE_INITIALIZED; + + return 0; +} + +int super_node_parse_uri(struct super_node *sn, const char *uri) +{ + info("Parsing configuration: uri=%s", uri); + + int ret = CONFIG_FALSE; + + if (uri) { INDENT + FILE *f; + AFILE *af; + config_setting_t *cfg_root; + + /* Via stdin */ + if (strcmp("-", uri) == 0) { + af = NULL; + f = stdin; + } + /* Local file? */ + else if (access(uri, F_OK) != -1) { + /* Setup libconfig include path. + * This is only supported for local files */ + char *uri_cpy = strdup(uri); + char *include_dir = dirname(uri_cpy); + + config_set_include_dir(&sn->cfg, include_dir); + + free(uri_cpy); + + af = NULL; + f = fopen(uri, "r"); + } + /* Use advio (libcurl) to fetch the config from a remote */ + else { + af = afopen(uri, "r"); + f = af ? af->file : NULL; + } + + /* Check if file could be loaded / opened */ + if (!f) + error("Failed to open configuration from: %s", uri); + + /* Parse config */ + config_set_auto_convert(&sn->cfg, 1); + ret = config_read(&sn->cfg, f); + if (ret != CONFIG_TRUE) + error("Failed to parse configuration: %s in %s:%d", config_error_text(&sn->cfg), uri, config_error_line(&sn->cfg)); + + cfg_root = config_root_setting(&sn->cfg); + + /* Little hack to properly report configuration filename in error messages + * We add the uri as a "hook" object to the root setting. + * See cerror() on how this info is used. + */ + config_setting_set_hook(cfg_root, strdup(uri)); + config_set_destructor(&sn->cfg, config_dtor); + + /* Close configuration file */ + if (af) + afclose(af); + else + fclose(f); + + return super_node_parse(sn, cfg_root); + } + else { INDENT + warn("No configuration file specified. Starting unconfigured. Use the API to configure this instance."); + } + + return 0; +} + +int super_node_parse_cli(struct super_node *sn, int argc, char *argv[]) +{ + char *uri = (argc == 2) ? argv[1] : NULL; + + sn->cli.argc = argc; + sn->cli.argv = argv; + + return super_node_parse_uri(sn, uri); +} + +int super_node_parse(struct super_node *sn, config_setting_t *cfg) +{ + int ret; + + assert(sn->state != STATE_STARTED); + assert(sn->state != STATE_DESTROYED); + + config_setting_t *cfg_nodes, *cfg_paths, *cfg_plugins, *cfg_logging, *cfg_web; + + super_node_parse_global(sn, cfg); + + cfg_web = config_setting_get_member(cfg, "http"); + if (cfg_web) + web_parse(&sn->web, cfg_web); + + /* Parse logging settings */ + cfg_logging = config_setting_get_member(cfg, "logging"); + if (cfg_logging) + log_parse(&sn->log, cfg_logging); + + /* Parse plugins */ + cfg_plugins = config_setting_get_member(cfg, "plugins"); + if (cfg_plugins) { + if (!config_setting_is_array(cfg_plugins)) + cerror(cfg_plugins, "Setting 'plugins' must be a list of strings"); + + for (int i = 0; i < config_setting_length(cfg_plugins); i++) { + struct config_setting_t *cfg_plugin = config_setting_get_elem(cfg_plugins, i); + + struct plugin plugin = { .state = STATE_DESTROYED }; + + ret = plugin_init(&plugin); + if (ret) + cerror(cfg_plugin, "Failed to initialize plugin"); + + ret = plugin_parse(&plugin, cfg_plugin); + if (ret) + cerror(cfg_plugin, "Failed to parse plugin"); + + list_push(&sn->plugins, memdup(&plugin, sizeof(plugin))); + } + } + + /* Parse nodes */ + cfg_nodes = config_setting_get_member(cfg, "nodes"); + if (cfg_nodes) { + if (!config_setting_is_group(cfg_nodes)) + warn("Setting 'nodes' must be a group with node name => group mappings."); + + for (int i = 0; i < config_setting_length(cfg_nodes); i++) { + config_setting_t *cfg_node = config_setting_get_elem(cfg_nodes, i); + + struct plugin *p; + const char *type; + + /* Required settings */ + if (!config_setting_lookup_string(cfg_node, "type", &type)) + cerror(cfg_node, "Missing node type"); + + p = plugin_lookup(PLUGIN_TYPE_NODE, type); + if (!p) + cerror(cfg_node, "Invalid node type: %s", type); + + struct node *n = alloc(sizeof(struct node)); + + n->state = STATE_DESTROYED; + + ret = node_init(n, &p->node); + if (ret) + cerror(cfg_node, "Failed to initialize node"); + + ret = node_parse(n, cfg_node); + if (ret) + cerror(cfg_node, "Failed to parse node"); + + list_push(&sn->nodes, n); + } + } + + /* Parse paths */ + cfg_paths = config_setting_get_member(cfg, "paths"); + if (cfg_paths) { + if (!config_setting_is_list(cfg_paths)) + warn("Setting 'paths' must be a list."); + + for (int i = 0; i < config_setting_length(cfg_paths); i++) { + config_setting_t *cfg_path = config_setting_get_elem(cfg_paths, i); + + struct path p = { .state = STATE_DESTROYED }; + + ret = path_init(&p, sn); + if (ret) + cerror(cfg_path, "Failed to init path"); + + ret = path_parse(&p, cfg_path, &sn->nodes); + if (ret) + cerror(cfg_path, "Failed to parse path"); + + list_push(&sn->paths, memdup(&p, sizeof(p))); + + if (p.reverse) { + struct path r; + + ret = path_init(&r, sn); + if (ret) + cerror(cfg_path, "Failed to init path"); + + ret = path_reverse(&p, &r); + if (ret) + cerror(cfg_path, "Failed to reverse path %s", path_name(&p)); + + list_push(&sn->paths, memdup(&r, sizeof(p))); + } + } + } + + sn->state = STATE_PARSED; + + return 0; +} + +int super_node_check(struct super_node *sn) +{ + int ret; + + for (size_t i = 0; i < list_length(&sn->nodes); i++) { + struct node *n = list_at(&sn->nodes, i); + + ret = node_check(n); + if (ret) + error("Invalid configuration for node %s", node_name(n)); + } + + for (size_t i = 0; i < list_length(&sn->paths); i++) { + struct path *p = list_at(&sn->paths, i); + + ret = path_check(p); + if (ret) + error("Invalid configuration for path %s", path_name(p)); + } + + sn->state = STATE_CHECKED; + + return 0; +} + +int super_node_start(struct super_node *sn) +{ + assert(sn->state == STATE_CHECKED); + + memory_init(sn->hugepages); + rt_init(sn->priority, sn->affinity); + + api_start(&sn->api); + web_start(&sn->web); + + info("Start node types"); + for (size_t i = 0; i < list_length(&sn->nodes); i++) { INDENT + struct node *n = list_at(&sn->nodes, i); + + node_type_start(n->_vt, sn); + } + + info("Starting nodes"); + for (size_t i = 0; i < list_length(&sn->nodes); i++) { INDENT + struct node *n = list_at(&sn->nodes, i); + + int refs = list_count(&sn->paths, (cmp_cb_t) path_uses_node, n); + if (refs > 0) + node_start(n); + else + warn("No path is using the node %s. Skipping...", node_name(n)); + } + + info("Starting paths"); + for (size_t i = 0; i < list_length(&sn->paths); i++) { INDENT + struct path *p = list_at(&sn->paths, i); + + if (p->enabled) { + path_init(p, sn); + path_start(p); + } + else + warn("Path %s is disabled. Skipping...", path_name(p)); + } + + sn->state = STATE_STARTED; + + return 0; +} + +int super_node_stop(struct super_node *sn) +{ + assert(sn->state == STATE_STARTED); + + info("Stopping paths"); + for (size_t i = 0; i < list_length(&sn->paths); i++) { INDENT + struct path *p = list_at(&sn->paths, i); + + path_stop(p); + } + + info("Stopping nodes"); + for (size_t i = 0; i < list_length(&sn->nodes); i++) { INDENT + struct node *n = list_at(&sn->nodes, i); + + node_stop(n); + } + + info("De-initializing node types"); + for (size_t i = 0; i < list_length(&plugins); i++) { INDENT + struct plugin *p = list_at(&plugins, i); + if (p->type == PLUGIN_TYPE_NODE) + node_type_stop(&p->node); + } + + web_stop(&sn->web); + api_stop(&sn->api); + log_stop(&sn->log); + + sn->state = STATE_STOPPED; + + return 0; +} + +int super_node_destroy(struct super_node *sn) +{ + assert(sn->state != STATE_DESTROYED); + + config_destroy(&sn->cfg); + + web_destroy(&sn->web); + log_destroy(&sn->log); + api_destroy(&sn->api); + + list_destroy(&sn->plugins, (dtor_cb_t) plugin_destroy, false); + list_destroy(&sn->paths, (dtor_cb_t) path_destroy, true); + list_destroy(&sn->nodes, (dtor_cb_t) node_destroy, true); + + sn->state = STATE_DESTROYED; + + return 0; +} \ No newline at end of file diff --git a/lib/timing.c b/lib/timing.c index 5d4b80d4f..cf48b9818 100644 --- a/lib/timing.c +++ b/lib/timing.c @@ -1,7 +1,7 @@ /** Time related functions. * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include diff --git a/lib/utils.c b/lib/utils.c index 6181a31df..6b15abbb8 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -1,7 +1,7 @@ /** General purpose helper functions. * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include @@ -11,20 +11,18 @@ #include #include #include -#include #include #include #include #include "config.h" -#include "cfg.h" #include "utils.h" void print_copyright() { printf("VILLASnode %s (built on %s %s)\n", - BLU(VERSION), MAG(__DATE__), MAG(__TIME__)); - printf(" copyright 2014-2016, Institute for Automation of Complex Power Systems, EONERC\n"); + BLU(BUILDID), MAG(__DATE__), MAG(__TIME__)); + printf(" Copyright 2014-2017, Institute for Automation of Complex Power Systems, EONERC\n"); printf(" Steffen Vogel \n"); } @@ -243,6 +241,22 @@ char *cpulist_create(char *str, size_t len, cpu_set_t *set) } #ifdef WITH_JANSSON +static int json_to_config_type(int type) +{ + switch (type) { + case JSON_OBJECT: return CONFIG_TYPE_GROUP; + case JSON_ARRAY: return CONFIG_TYPE_LIST; + case JSON_STRING: return CONFIG_TYPE_STRING; + case JSON_INTEGER: return CONFIG_TYPE_INT64; + case JSON_REAL: return CONFIG_TYPE_FLOAT; + case JSON_TRUE: + case JSON_FALSE: + case JSON_NULL: return CONFIG_TYPE_BOOL; + } + + return -1; +} + json_t * config_to_json(config_setting_t *cfg) { switch (config_setting_type(cfg)) { @@ -265,19 +279,83 @@ json_t * config_to_json(config_setting_t *cfg) case CONFIG_TYPE_GROUP: { json_t *json = json_object(); - for (int i = 0; i < config_setting_length(cfg); i++) + for (int i = 0; i < config_setting_length(cfg); i++) { json_object_set_new(json, config_setting_name(config_setting_get_elem(cfg, i)), config_to_json(config_setting_get_elem(cfg, i)) ); - + } + return json; } - + default: return json_object(); } } + +int json_to_config(json_t *json, config_setting_t *parent) +{ + config_setting_t *cfg; + int ret, type; + + if (config_setting_is_root(parent)) { + if (!json_is_object(json)) + return -1; /* The root must be an object! */ + } + + switch (json_typeof(json)) { + case JSON_OBJECT: { + const char *key; + json_t *json_value; + + json_object_foreach(json, key, json_value) { + type = json_to_config_type(json_typeof(json_value)); + + cfg = config_setting_add(parent, key, type); + ret = json_to_config(json_value, cfg); + if (ret) + return ret; + } + break; + } + + case JSON_ARRAY: { + size_t i; + json_t *json_value; + + json_array_foreach(json, i, json_value) { + type = json_to_config_type(json_typeof(json_value)); + + cfg = config_setting_add(parent, NULL, type); + ret = json_to_config(json_value, cfg); + if (ret) + return ret; + } + break; + } + + case JSON_STRING: + config_setting_set_string(parent, json_string_value(json)); + break; + + case JSON_INTEGER: + config_setting_set_int64(parent, json_integer_value(json)); + break; + + case JSON_REAL: + config_setting_set_float(parent, json_real_value(json)); + break; + + case JSON_TRUE: + case JSON_FALSE: + case JSON_NULL: + config_setting_set_bool(parent, json_is_true(json)); + break; + } + + return 0; +} #endif void * alloc(size_t bytes) @@ -300,68 +378,28 @@ void * memdup(const void *src, size_t bytes) return dst; } -int read_random(char *buf, size_t len) +ssize_t read_random(char *buf, size_t len) { int fd; - + ssize_t bytes, total; + fd = open("/dev/urandom", O_RDONLY); if (fd < 0) return -1; - - ssize_t bytes, total = 0; - + + bytes = 0; + total = 0; while (total < len) { bytes = read(fd, buf + total, len - total); if (bytes < 0) - goto out; + break; total += bytes; } close(fd); - return 0; -out: - close(fd); - - return -1; -} - -void printb(void *mem, size_t len) -{ - uint8_t *mem8 = (uint8_t *) mem; - - for (int i = 0; i < len; i++) { - printf("%02hx ", mem8[i]); - - if (i % 16 == 15) - printf("\n"); - } -} - -void printdw(void *mem, size_t len) -{ - int columns = 4; - - uint32_t *mem32 = (uint32_t *) mem; - - for (int i = 0; i < len; i++) { - if (i % columns == 0) - printf("%#x: ", i * 4); - - printf("%08x ", mem32[i]); - - char *memc = (char *) &mem32[i]; - printf("%c%c%c%c ", - isprint(memc[0]) ? memc[0] : ' ', - isprint(memc[1]) ? memc[1] : ' ', - isprint(memc[2]) ? memc[2] : ' ', - isprint(memc[3]) ? memc[3] : ' ' - ); - - if ((i+1) % columns == 0) - printf("\n"); - } + return bytes; } void rdtsc_sleep(uint64_t nanosecs, uint64_t start) @@ -377,4 +415,40 @@ void rdtsc_sleep(uint64_t nanosecs, uint64_t start) do { __asm__("nop"); } while (rdtsc() - start < cycles); +} + +/* Setup exit handler */ +void signals_init(void (*cb)(int signal, siginfo_t *sinfo, void *ctx)) +{ + info("Initialize signals"); + + struct sigaction sa_quit = { + .sa_flags = SA_SIGINFO, + .sa_sigaction = cb + }; + + sigemptyset(&sa_quit.sa_mask); + sigaction(SIGINT, &sa_quit, NULL); + sigaction(SIGTERM, &sa_quit, NULL); +} + +int sha1sum(FILE *f, unsigned char *sha1) +{ + SHA_CTX c; + char buf[512]; + ssize_t bytes; + + rewind(f); /* Rewind the file in order to calculate over the whole file. */ + + SHA1_Init(&c); + + bytes = fread(buf, 1, 512, f); + while (bytes > 0) { + SHA1_Update(&c, buf, bytes); + bytes = fread(buf, 1, 512, f); + } + + SHA1_Final(sha1, &c); + + return 0; } \ No newline at end of file diff --git a/lib/web.c b/lib/web.c new file mode 100644 index 000000000..484bd736d --- /dev/null +++ b/lib/web.c @@ -0,0 +1,221 @@ +/** LWS-releated functions. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#include +#include + +#include + +#include "utils.h" +#include "log.h" +#include "web.h" +#include "api.h" + +#include "nodes/websocket.h" + +/* Forward declarations */ +lws_callback_function api_ws_protocol_cb; +lws_callback_function api_http_protocol_cb; +lws_callback_function websocket_protocol_cb; + +/** List of libwebsockets protocols. */ +static struct lws_protocols protocols[] = { + { + .name = "http-api", + .callback = api_http_protocol_cb, + .per_session_data_size = sizeof(struct api_session), + .rx_buffer_size = 0 + }, + { + .name = "api", + .callback = api_ws_protocol_cb, + .per_session_data_size = sizeof(struct api_session), + .rx_buffer_size = 0 + }, +#if 0 /* not supported yet */ + { + .name = "log", + .callback = log_ws_protocol_cb, + .per_session_data_size = 0, + .rx_buffer_size = 0 + }, + { + .name = "stats", + .callback = stats_ws_protocol_cb, + .per_session_data_size = sizeof(struct api_session), + .rx_buffer_size = 0 + }, +#endif + { + .name = "live", + .callback = websocket_protocol_cb, + .per_session_data_size = sizeof(struct websocket_connection), + .rx_buffer_size = 0 + }, + { NULL /* terminator */ } +}; + +/** List of libwebsockets mounts. */ +static struct lws_http_mount mounts[] = { + { + .mount_next = &mounts[1], + .mountpoint = "/", + .origin = NULL, + .def = "/index.html", + .cgienv = NULL, + .cgi_timeout = 0, + .cache_max_age = 0, + .cache_reusable = 0, + .cache_revalidate = 0, + .cache_intermediaries = 0, + .origin_protocol = LWSMPRO_FILE, + .mountpoint_len = 1 + }, + { + .mount_next = NULL, + .mountpoint = "/api/v1/", + .origin = "http-api", + .def = NULL, + .cgienv = NULL, + .cgi_timeout = 0, + .cache_max_age = 0, + .cache_reusable = 0, + .cache_revalidate = 0, + .cache_intermediaries = 0, + .origin_protocol = LWSMPRO_CALLBACK, + .mountpoint_len = 8 + } +}; + +/** List of libwebsockets extensions. */ +static const struct lws_extension extensions[] = { + { + "permessage-deflate", + lws_extension_callback_pm_deflate, + "permessage-deflate" + }, + { + "deflate-frame", + lws_extension_callback_pm_deflate, + "deflate_frame" + }, + { NULL /* terminator */ } +}; + +static void logger(int level, const char *msg) { + int len = strlen(msg); + if (strchr(msg, '\n')) + len -= 1; + + /* Decrease severity for some errors. */ + if (strstr(msg, "Unable to open") == msg) + level = LLL_WARN; + + switch (level) { + case LLL_ERR: error("LWS: %.*s", len, msg); break; + case LLL_WARN: warn("LWS: %.*s", len, msg); break; + case LLL_INFO: info("LWS: %.*s", len, msg); break; + default: debug(LOG_WEBSOCKET | 1, "LWS: %.*s", len, msg); break; + } +} + +int web_init(struct web *w, struct api *a) +{ + lws_set_log_level((1 << LLL_COUNT) - 1, logger); + + w->api = a; + + w->state = STATE_INITIALIZED; + + return 0; +} + +int web_parse(struct web *w, config_setting_t *cfg) +{ + if (!config_setting_is_group(cfg)) + cerror(cfg, "Setting 'http' must be a group."); + + config_setting_lookup_string(cfg, "ssl_cert", &w->ssl_cert); + config_setting_lookup_string(cfg, "ssl_private_key", &w->ssl_private_key); + + if (!config_setting_lookup_int(cfg, "port", &w->port)) + w->port = 80; + + if (!config_setting_lookup_string(cfg, "htdocs", &w->htdocs)) + w->htdocs = "/usr/share/villas/htdocs"; + + w->state = STATE_PARSED; + + return 0; +} + +int web_start(struct web *w) +{ + /* Start server */ + struct lws_context_creation_info ctx_info = { + .options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT, + .gid = -1, + .uid = -1, + .user = (void *) w + }; + + struct lws_context_creation_info vhost_info = { + .protocols = protocols, + .mounts = mounts, + .extensions = extensions, + .port = w->port, + .ssl_cert_filepath = w->ssl_cert, + .ssl_private_key_filepath = w->ssl_private_key + }; + + info("Starting web sub-system"); + + { INDENT + /* update web root of mount point */ + mounts[0].origin = w->htdocs; + + w->context = lws_create_context(&ctx_info); + if (w->context == NULL) + error("WebSocket: failed to initialize server"); + + w->vhost = lws_create_vhost(w->context, &vhost_info); + if (w->vhost == NULL) + error("WebSocket: failed to initialize server"); + } + + w->state = STATE_STARTED; + + return 0; +} + +int web_stop(struct web *w) +{ + assert(w->state == STATE_STARTED); + + lws_cancel_service(w->context); + + w->state = STATE_STOPPED; + + return 0; +} + +int web_destroy(struct web *w) +{ + assert(w->state != STATE_DESTROYED && w->state != STATE_STARTED); + + lws_context_destroy(w->context); + + w->state = STATE_DESTROYED; + + return 0; +} + +int web_service(struct web *w) +{ + assert(w->state == STATE_STARTED); + + return lws_service(w->context, 10); +} diff --git a/packaging/Makefile.inc b/packaging/Makefile.inc new file mode 100644 index 000000000..0d823382d --- /dev/null +++ b/packaging/Makefile.inc @@ -0,0 +1,42 @@ +TAROPTS = --exclude-ignore-recursive=.distignore --transform='s|^\.|villas-node-$(VERSION_NUM)|' --show-transformed-names + +TAR_VILLAS = $(BUILDDIR)/packaging/villas-node-$(VERSION_NUM).tar.gz + +DEPLOY_HOST = root@villas.0l.de +DEPLOY_PATH = /var/www/villas + +packaging: rpm dist + +deploy: deploy-dist deploy-rpm + +# Source tarballs +dist: $(TAR_VILLAS) + +$(TAR_VILLAS): | $$(dir $$@) + tar $(TAROPTS) -C $(SRCDIR) -czf $@ . + +deploy-dist: $(TAR_VILLAS) + rsync $(TAR_VILLAS) $(DEPLOY_HOST):$(DEPLOY_PATH)/node/src + +deploy-rpm: + rsync -a --progress $(RPMDIR)/RPMS/ $(DEPLOY_HOST):$(DEPLOY_PATH)/packages/ + ssh $(DEPLOY_HOST) createrepo $(DEPLOY_PATH)/packages + +# Docker targets +run-docker-dev: + docker run -it -p 80:80 -p 443:443 -p 1234:1234 --privileged --cap-add sys_nic --ulimit memlock=1073741824 --security-opt seccomp:unconfined -v $(PWD):/villas villas-dev + +docker-dev: + docker build -f Dockerfile.dev -t villas-dev $(SRCDIR) + +docker: + docker build -f Dockerfile -t villas $(SRCDIR) + +clean-packaging: + rm -f $(BUILDDIR)/packaging/villas-node-$(VERSION_NUM).tar.gz + +install-packaging: + +.PHONY: packaging install-packaging clean-packaging deploy deploy-dist deploy-rpm dist docker docker-dev run-docker-dev $(TAR_VILLAS) + +-include packaging/rpm/Makefile.inc \ No newline at end of file diff --git a/packaging/rpm/Makefile.inc b/packaging/rpm/Makefile.inc new file mode 100644 index 000000000..556ec72c2 --- /dev/null +++ b/packaging/rpm/Makefile.inc @@ -0,0 +1,37 @@ +RPMDIR = $(BUILDDIR)/packaging/rpm + +SPEC_VILLAS = $(BUILDDIR)/packaging/rpm/villas-node.spec + +# Increment this number for minor release bumps +MINOR = 2 + +rpm: rpm-villas rpm-libwebsockets rpm-libxil + +rpm-villas: $(TAR_VILLAS) $(SPEC_VILLAS) | $(RPMDIR)/SOURCES/ + cp $(BUILDDIR)/packaging/villas-node-$(VERSION_NUM).tar.gz $(RPMDIR)/SOURCES + rpmbuild -ba --define="_topdir $$(pwd)/$(RPMDIR)" $(BUILDDIR)/packaging/rpm/villas-node.spec + +rpm-libxil: $(BUILDDIR)/thirdparty/libxil/ + cmake -DCMAKE_INSTALL_PREFIX:PATH=$(PREFIX) \ + -H$(SRCDIR)/thirdparty/libxil \ + -B$(BUILDDIR)/thirdparty/libxil $(CMAKE_OPTS) + make -C$(BUILDDIR)/thirdparty/libxil package_source + cp $(BUILDDIR)/thirdparty/libxil/libxil-*.tar.gz $(RPMDIR)/SOURCES + rpmbuild -ba --define="_topdir $$(pwd)/$(RPMDIR)" $(SRCDIR)/thirdparty/libxil/libxil.spec + +rpm-libwebsockets: | $(RPMDIR)/RPMS $(BUILDDIR)/thirdparty/libwebsockets/ + cmake -DCMAKE_INSTALL_PREFIX:PATH=$(PREFIX) \ + -H$(SRCDIR)/thirdparty/libwebsockets \ + -B$(BUILDDIR)/thirdparty/libwebsockets $(CMAKE_OPTS) + make -C$(BUILDDIR)/thirdparty/libwebsockets libwebsockets_rpm + mv $(BUILDDIR)/thirdparty/libwebsockets/RPM/RPMS/x86_64/libwebsockets-*.rpm $(RPMDIR)/RPMS/x86_64/ + +# We patch version number and release fields of the spec file based on the current Git commit +$(SPEC_VILLAS): $(SRCDIR)/packaging/rpm/villas-node.spec | $$(dir $$@) + sed -e "s/§VERSION§/$(VERSION_NUM)/g" \ + -e "s/§RELEASE§/$(MINOR).$(VARIANT).$$(date +%Y%m%d)git$$(echo $(GIT_REV) | cut -b1-7)/g" < $^ > $@ + +clean-rpm: + rm -rf $(RPMDIR) + +.PHONY: rpm clean-rpm rpm-libwebsockets rpm-libxil \ No newline at end of file diff --git a/packaging/rpm/villas-node.spec b/packaging/rpm/villas-node.spec new file mode 100644 index 000000000..ecfe5341f --- /dev/null +++ b/packaging/rpm/villas-node.spec @@ -0,0 +1,79 @@ +Name: villas-node +Version: §VERSION§ +Vendor: Institute for Automation of Complex Power Systems +Packager: Steffen Vogel +Release: §RELEASE§%{?dist} +Summary: This is VILLASnode, a gateway for processing and forwardning simulation data between real-time simulators. + +License: LGPLv2 +URL: https://git.rwth-aachen.de/VILLASframework/VILLASnode +Source0: villas-node-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) + +BuildRequires: gcc pkgconfig make + +Requires: iproute kernel-modules-extra + +BuildRequires: openssl-devel libconfig-devel libnl3-devel libcurl-devel jansson-devel libxil-devel libwebsockets-devel +Requires: openssl libconfig libnl3 libcurl jansson libxil libwebsockets + +%description + +%package doc + +Summary: HTML documentation for users and developers. +Group: Documentation + +%package devel + +Summary: Headers and libraries for building apps that use libvillas. +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel + +The development headers for libvillas. + +%description doc + +%prep +%setup -q + +%build +make PREFIX=/usr + +%install +rm -rf %{?buildroot} +make PREFIX=/usr DESTDIR=%{?buildroot} install +make PREFIX=/usr DESTDIR=%{?buildroot} install-doc + +%post -p /sbin/ldconfig +%postun -p /sbin/ldconfig + +%clean +rm -rf %{?buildroot} + +%files +/usr/bin/villas +/usr/bin/villas-* +/usr/bin/conf2json + +/usr/lib/libvillas.so +/usr/lib/libvillas.so.* + +/usr/share/villas/node/web/ +/usr/share/villas/node/plugins/ + +%config /etc/villas/node/*.conf +%license COPYING.md + +%files doc +%docdir /usr/share/villas/node/doc/ +/usr/share/villas/node/doc/ + +%files devel +/usr/include/villas/ + +%changelog +* Fri Mar 17 2017 Steffen Vogel -#include +/** A simple example hook function which can be loaded as a plugin. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ -static int hook_example(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt) +#include + +#include +#include +#include + +struct hook; +struct path; +struct sample; + +static int example_start(struct hook *h) { info("Hello world from example hook!"); - + return 0; } -REGISTER_HOOK("example", "This is just a simple example hook", 99, 0, hook_example, HOOK_PATH_START) \ No newline at end of file +static struct plugin p = { + .name = "example", + .description = "This is just a simple example hook", + .type = PLUGIN_TYPE_HOOK, + .hook = { + .priority = 99, + .start = example_start + } +}; + +REGISTER_PLUGIN(&p) \ No newline at end of file diff --git a/plugins/models/simple_circuit.c b/plugins/models/simple_circuit.c index 3ab7934b8..aae8d050c 100644 --- a/plugins/models/simple_circuit.c +++ b/plugins/models/simple_circuit.c @@ -1,126 +1,126 @@ -// This is c-code for CBuilder component for Subsystem 2 -// Solver used as in RTDS: Resistive companion (Dommel's algo) -// Subsystem 1 is modelled in RSCAD -// -//% Circuit topology -// % -//% *** Subsystem 1 (SS1) *** % *** Subsystem 2 (SS2) *** -//% % -//% |---------| |---------| % -//% |---------| R1 |-------| L1 |----%-------|---------| -//% | |---------| |---------| % | | -//% | % | | -//% ----- % ----- ----- -//% | + | % | | | | -//% | E | % |C2 | | R2| -//% | - | % | | | | -//% ----- % ----- ----- -//% | % | | -//% |------------------------------------------%------------------ -// % -// % +/** This is c-code for CBuilder component for Subsystem 2 + * Solver used as in RTDS: Resistive companion (Dommel's algo) + * Subsystem 1 is modelled in RSCAD + * + * % Circuit topology + * % + * % *** Subsystem 1 (SS1) *** % *** Subsystem 2 (SS2) *** + * % % + * % |---------| |---------| % + * % |---------| R1 |-------| L1 |----%-------|---------| + * % | |---------| |---------| % | | + * % | % | | + * % ----- % ----- ----- + * % | + | % | | | | + * % | E | % |C2 | | R2| + * % | - | % | | | | + * % ----- % ----- ----- + * % | % | | + * % |------------------------------------------%------------------ + * % + * % + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ -// ----------------------------------------------- -// Variables declared here may be used as parameters -// inputs or outputs -// The have to match with whats in Subsystem.h -// ----------------------------------------------- +/* Variables declared here may be used as parameters inputs or outputs + * The have to match with whats in Subsystem.h */ #if defined(VILLAS) || SECTION == INPUTS double IntfIn; -#endif +#endif /* defined(VILLAS) || SECTION == INPUTS */ #if defined(VILLAS) || SECTION == OUTPUTS double IntfOut; -#endif +#endif /* defined(VILLAS) || SECTION == OUTPUTS */ #if defined(VILLAS) || SECTION == PARAMS -double R2; // Resistor [Ohm] in SS2 -double C2; // Capacitance [F] in SS2 -#endif +double R2; /**< Resistor [Ohm] in SS2 */ +double C2; /**< Capacitance [F] in SS2 */ +#endif /* defined(VILLAS) || SECTION == PARAMS */ -// ----------------------------------------------- -// Variables declared here may be used in both the -// RAM: and CODE: sections below. -// ----------------------------------------------- +/* Variables declared here may be used in both the RAM: and CODE: sections below. */ #if defined(VILLAS) || SECTION == STATIC -double dt; -double GR2, GC2; //Inductances of components -double GnInv; //Inversion of conductance matrix (here only scalar) -double vC2Hist, iC2Hist, AC2; // history meas. and current of dynamic elements -double Jn; //source vector in equation Gn*e=Jn -double eSS2; //node voltage solution -#endif +double dt; +double GR2, GC2; /**< Inductances of components */ +double GnInv; /**< Inversion of conductance matrix (here only scalar) */ +double vC2Hist, iC2Hist, AC2; /**< History meas. and current of dynamic elements */ +double Jn; /**< Source vector in equation Gn*e=Jn */ +double eSS2; /**< Node voltage solution */ +#endif /* defined(VILLAS) || SECTION == STATIC */ -// ----------------------------------------------- -// This section should contain any 'c' functions -// to be called from the RAM section (either -// RAM_PASS1 or RAM_PASS2). Example: -// -// static double myFunction(double v1, double v2) -// { -// return(v1*v2); -// } -// ----------------------------------------------- + +/* This section should contain any 'c' functions + * to be called from the RAM section (either + * RAM_PASS1 or RAM_PASS2). Example: + * + * static double myFunction(double v1, double v2) + * { + * return(v1*v2); + * } + */ #if defined(VILLAS) || SECTION == RAM_FUNCTIONS -/* Nothing here */ -#endif -// ----------------------------------------------- -// Place C code here which computes constants -// required for the CODE: section below. The C -// code here is executed once, prior to the start -// of the simulation case. -// ----------------------------------------------- +/* Nothing here */ + +#endif /* defined(VILLAS) || SECTION == RAM_FUNCTIONS */ + + +/* Place C code here which computes constants + * required for the CODE: section below. The C + * code here is executed once, prior to the start + * of the simulation case. + */ #if defined(VILLAS) || SECTION == RAM void simple_circuit_ram() { - GR2 = 1/R2; - GC2 = 2*C2/dt; //trapezoidal rule - GnInv = 1/(GR2+GC2); //eq. conductance (inverted) - - vC2Hist = 0.0; //Voltage over C2 in previous time step - iC2Hist = 0.0; //Current through C2 in previous time step + GR2 = 1/R2; + GC2 = 2*C2/dt; /**< Trapezoidal rule */ + GnInv = 1/(GR2+GC2); /**< eq. conductance (inverted) */ + + vC2Hist = 0.0; /**< Voltage over C2 in previous time step */ + iC2Hist = 0.0; /**< Current through C2 in previous time step */ } -#endif +#endif /* defined(VILLAS) || SECTION == RAM */ -// ----------------------------------------------- -// Place C code here which runs on the RTDS. The -// code below is entered once each simulation -// step. + +// ----------------------------------------------- +// Place C code here which runs on the RTDS. The +// code below is entered once each simulation +// step. // ----------------------------------------------- #if defined(VILLAS) || SECTION == CODE void simple_circuit_code() { - //Update source vector + /* Update source vector */ AC2 = iC2Hist+vC2Hist*GC2; Jn = IntfIn+AC2; - //Solution of the equation Gn*e=Jn; - eSS2 = GnInv*Jn; - //Post step -> calculate the voltage and current for C2 for next step and set interface output + + /* Solution of the equation Gn*e=Jn; */ + eSS2 = GnInv*Jn; + + /* Post step -> calculate the voltage and current for C2 for next step and set interface output */ vC2Hist= eSS2; iC2Hist = vC2Hist*GC2-AC2; IntfOut = eSS2; } -#endif +#endif /* defined(VILLAS) || SECTION == CODE */ -// ----------------------------------------------- -// Interface to VILLASnode -// ----------------------------------------------- +/* Interface to VILLASnode */ #if defined(VILLAS) -#include "nodes/cbuilder.h" +#include +#include double getTimeStep() { return dt; } -// ----------------------------------------------- -// Place C code here which intializes parameters -// ----------------------------------------------- +/** Place C code here which intializes parameters */ int simple_circuit_init(struct cbuilder *cb) { if (cb->paramlen < 2) @@ -135,9 +135,7 @@ int simple_circuit_init(struct cbuilder *cb) return 0; /* success */ } -// ----------------------------------------------- -// Place C code here reads model outputs -// ----------------------------------------------- +/** Place C code here reads model outputs */ int simple_circuit_read(float outputs[], int len) { if (len < 1) @@ -148,9 +146,7 @@ int simple_circuit_read(float outputs[], int len) return 1; /* 1 value per sample */ } -// ----------------------------------------------- -// Place C code here which updates model inputs -// ----------------------------------------------- +/** Place C code here which updates model inputs */ int simple_circuit_write(float inputs[], int len) { if (len < 1) @@ -161,15 +157,19 @@ int simple_circuit_write(float inputs[], int len) return 0; } -static struct cbmodel cb = { - .name = "simple_circuit", - .code = simple_circuit_code, - .init = simple_circuit_init, - .read = simple_circuit_read, - .write = simple_circuit_write, - .ram = simple_circuit_ram +static struct plugin p = { + .name = "simple_circuit", + .description = "A simple CBuilder model", + .type = PLUGIN_TYPE_MODEL_CBUILDER, + .cb = { + .code = simple_circuit_code, + .init = simple_circuit_init, + .read = simple_circuit_read, + .write = simple_circuit_write, + .ram = simple_circuit_ram + } }; -REGISTER_CBMODEL(&cb); +REGISTER_PLUGIN(&p) -#endif \ No newline at end of file +#endif /* defined(VILLAS) */ \ No newline at end of file diff --git a/src/Makefile.inc b/src/Makefile.inc index 280efdbe2..b4a107e34 100644 --- a/src/Makefile.inc +++ b/src/Makefile.inc @@ -2,7 +2,9 @@ TARGETS = $(BUILDDIR)/villas-node \ $(BUILDDIR)/villas-pipe \ $(BUILDDIR)/villas-signal \ - $(BUILDDIR)/villas-test + $(BUILDDIR)/villas-test-rtt \ + $(BUILDDIR)/villas-test-cmp \ + $(BUILDDIR)/villas-hook SRC_LDLIBS = $(LDLIBS) -pthread -lm -lvillas SRC_CFLAGS = $(CFLAGS) @@ -28,11 +30,10 @@ src: $(TARGETS) $(TARGETS): $(BUILDDIR)/villas-%: $(BUILDDIR)/src/%.o # Some additional prereqs for individual binaries -$(BUILDDIR)/villas-fpga: $(addprefix $(BUILDDIR)/src/,fpga-tests.o fpga-bench.o $(BENCH_OBJS)) - +$(BUILDDIR)/villas-fpga: $(addprefix $(BUILDDIR)/src/,fpga-bench.o $(BENCH_OBJS)) # Compile executable objects -$(BUILDDIR)/src/%.o: src/%.c | $$(dir $$@) +$(BUILDDIR)/src/%.o: src/%.c $(BUILDDIR)/defines | $$(dir $$@) $(CC) $(SRC_CFLAGS) -c $< -o $@ # Link target executables @@ -41,7 +42,7 @@ $(TARGETS): | $(LIBS) # Install install-src: src - install -m 0755 $(TARGETS) $(PREFIX)/bin + install -m 0755 -D -t $(DESTDIR)$(PREFIX)/bin $(TARGETS) clean-src: rm -rf $(BUILDDIR)/src $(TARGETS) diff --git a/src/fpga-bench-overruns.c b/src/fpga-bench-overruns.c index 2e980b388..0f0a53ef5 100644 --- a/src/fpga-bench-overruns.c +++ b/src/fpga-bench-overruns.c @@ -1,14 +1,13 @@ /** Benchmarks for VILLASfpga: LAPACK & BLAS * * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel **********************************************************************************/ #include #include #include -#include #include "config.h" @@ -61,13 +60,13 @@ static int lapack_workload(int N, double *A) return 0; } -int fpga_benchmark_overruns(struct fpga *f) +int fpga_benchmark_overruns(struct fpga_card *c) { - struct ip *rtds, *dm; + struct fpga_ip *rtds, *dm; - dm = list_lookup(&f->ips, "dma_1"); - rtds = list_lookup(&f->ips, "rtds_axis_0"); - if (!rtds || !f->intc) + dm = list_lookup(&c->ips, "dma_1"); + rtds = list_lookup(&c->ips, "rtds_axis_0"); + if (!rtds || !c->intc) return -1; int ret; @@ -77,10 +76,10 @@ int fpga_benchmark_overruns(struct fpga *f) info("runs = %u", runs); - switch_connect(f->sw, dm, rtds); - switch_connect(f->sw, rtds, dm); + switch_connect(c->sw, dm, rtds); + switch_connect(c->sw, rtds, dm); - intc_enable(f->intc, (1 << (dm->irq + 1 )), intc_flags); + intc_enable(c->intc, (1 << (dm->irq + 1 )), intc_flags); /* Dump results */ char fn[256]; diff --git a/src/fpga-bench.c b/src/fpga-bench.c index 8c7b465f3..d244134f0 100644 --- a/src/fpga-bench.c +++ b/src/fpga-bench.c @@ -1,44 +1,43 @@ /** Benchmarks for VILLASfpga * * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel **********************************************************************************/ #include -#include #include -#include #include #include #include #include -#include -#include -#include -#include +#include +#include + +#include +#include #include "config.h" -int fpga_benchmark_datamover(struct fpga *f); -int fpga_benchmark_jitter(struct fpga *f); -int fpga_benchmark_memcpy(struct fpga *f); -int fpga_benchmark_latency(struct fpga *f); +int fpga_benchmark_datamover(struct fpga_card *c); +int fpga_benchmark_jitter(struct fpga_card *c); +int fpga_benchmark_memcpy(struct fpga_card *c); +int fpga_benchmark_latency(struct fpga_card *c); #if defined(WITH_BLAS) && defined(WITH_LAPACK) -int fpga_benchmark_overruns(struct fpga *f); +int fpga_benchmark_overruns(struct fpga_card *c); #endif int intc_flags = 0; struct utsname uts; -int fpga_benchmarks(int argc, char *argv[], struct fpga *f) +int fpga_benchmarks(int argc, char *argv[], struct fpga_card *c) { int ret; struct bench { const char *name; - int (*func)(struct fpga *f); + int (*func)(struct fpga_card *c); } benchmarks[] = { { "datamover", fpga_benchmark_datamover }, { "jitter", fpga_benchmark_jitter }, @@ -67,7 +66,7 @@ int fpga_benchmarks(int argc, char *argv[], struct fpga *f) if (ret) return -1; -again: ret = bench->func(f); +again: ret = bench->func(c); if (ret) error("Benchmark %s failed", bench->name); @@ -81,19 +80,19 @@ again: ret = bench->func(f); return -1; } -int fpga_benchmark_jitter(struct fpga *f) +int fpga_benchmark_jitter(struct fpga_card *c) { int ret; - struct ip *tmr; - - tmr = list_lookup(&f->ips, "timer_0"); - if (!tmr || !f->intc) + struct fpga_ip *ip = list_lookup(&c->ips, "timer_0"); + if (!ip || !c->intc) return -1; - XTmrCtr *xtmr = &tmr->timer.inst; + struct timer *tmr = ip->_vd; - ret = intc_enable(f->intc, (1 << tmr->irq), intc_flags); + XTmrCtr *xtmr = &tmr->inst; + + ret = intc_enable(c->intc, (1 << ip->irq), intc_flags); if (ret) error("Failed to enable interrupt"); @@ -108,12 +107,12 @@ int fpga_benchmark_jitter(struct fpga *f) uint64_t end, start = rdtsc(); for (int i = 0; i < runs; i++) { - uint64_t cnt = intc_wait(f->intc, tmr->irq); + uint64_t cnt = intc_wait(c->intc, ip->irq); if (cnt != 1) warn("fail"); /* Ackowledge IRQ */ - XTmrCtr_WriteReg((uintptr_t) f->map + tmr->baseaddr, 0, XTC_TCSR_OFFSET, XTmrCtr_ReadReg((uintptr_t) f->map + tmr->baseaddr, 0, XTC_TCSR_OFFSET)); + XTmrCtr_WriteReg((uintptr_t) c->map + ip->baseaddr, 0, XTC_TCSR_OFFSET, XTmrCtr_ReadReg((uintptr_t) c->map + ip->baseaddr, 0, XTC_TCSR_OFFSET)); end = rdtsc(); hist[i] = end - start; @@ -131,34 +130,34 @@ int fpga_benchmark_jitter(struct fpga *f) free(hist); - ret = intc_disable(f->intc, (1 << tmr->irq)); + ret = intc_disable(c->intc, (1 << ip->irq)); if (ret) error("Failed to disable interrupt"); return 0; } -int fpga_benchmark_latency(struct fpga *f) +int fpga_benchmark_latency(struct fpga_card *c) { int ret; uint64_t start, end; - if (!f->intc) + if (!c->intc) return -1; int runs = 1000000; int hist[runs]; - ret = intc_enable(f->intc, 0x100, intc_flags); + ret = intc_enable(c->intc, 0x100, intc_flags); if (ret) error("Failed to enable interrupts"); for (int i = 0; i < runs; i++) { start = rdtsc(); - XIntc_Out32((uintptr_t) f->map + f->intc->baseaddr + XIN_ISR_OFFSET, 0x100); + XIntc_Out32((uintptr_t) c->map + c->intc->baseaddr + XIN_ISR_OFFSET, 0x100); - intc_wait(f->intc, 8); + intc_wait(c->intc, 8); end = rdtsc(); hist[i] = end - start; @@ -171,18 +170,18 @@ int fpga_benchmark_latency(struct fpga *f) fprintf(g, "%u\n", hist[i]); fclose(g); - ret = intc_disable(f->intc, 0x100); + ret = intc_disable(c->intc, 0x100); if (ret) error("Failed to disable interrupt"); return 0; } -int fpga_benchmark_datamover(struct fpga *f) +int fpga_benchmark_datamover(struct fpga_card *c) { int ret; - struct ip *dm; + struct fpga_ip *dm; struct dma_mem mem, src, dst; #if BENCH_DM == 1 @@ -193,15 +192,15 @@ int fpga_benchmark_datamover(struct fpga *f) char *dm_name = "dma_1"; #endif - dm = list_lookup(&f->ips, dm_name); + dm = list_lookup(&c->ips, dm_name); if (!dm) error("Unknown datamover"); - ret = switch_connect(f->sw, dm, dm); + ret = switch_connect(c->sw, dm, dm); if (ret) error("Failed to configure switch"); - ret = intc_enable(f->intc, (1 << dm->irq) | (1 << (dm->irq + 1)), intc_flags); + ret = intc_enable(c->intc, (1 << dm->irq) | (1 << (dm->irq + 1)), intc_flags); if (ret) error("Failed to enable interrupt"); @@ -268,7 +267,7 @@ int fpga_benchmark_datamover(struct fpga *f) fclose(g); - ret = switch_disconnect(f->sw, dm, dm); + ret = switch_disconnect(c->sw, dm, dm); if (ret) error("Failed to configure switch"); @@ -276,7 +275,7 @@ int fpga_benchmark_datamover(struct fpga *f) if (ret) error("Failed to release DMA memory"); - ret = intc_disable(f->intc, (1 << dm->irq) | (1 << (dm->irq + 1))); + ret = intc_disable(c->intc, (1 << dm->irq) | (1 << (dm->irq + 1))); if (ret) error("Failed to enable interrupt"); @@ -284,9 +283,9 @@ int fpga_benchmark_datamover(struct fpga *f) return 0; } -int fpga_benchmark_memcpy(struct fpga *f) +int fpga_benchmark_memcpy(struct fpga_card *c) { - char *map = f->map + 0x200000; + char *map = c->map + 0x200000; uint32_t *mapi = (uint32_t *) map; char fn[256]; diff --git a/src/fpga-tests.c b/src/fpga-tests.c deleted file mode 100644 index 160e53e68..000000000 --- a/src/fpga-tests.c +++ /dev/null @@ -1,410 +0,0 @@ -/** Test procedures for VILLASfpga - * - * @author Steffen Vogel - * @copyright 2016, Steffen Vogel - *********************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include - -#include "config.h" - -#define TEST_LEN 0x1000 - -#define CPU_HZ 3392389000 - -/* Forward Declarations */ -int fpga_test_intc(struct fpga *f); -int fpga_test_timer(struct fpga *f); -int fpga_test_fifo(struct fpga *f); -int fpga_test_dma(struct fpga *f); -int fpga_test_xsg(struct fpga *f); -int fpga_test_hls_dft(struct fpga *f); -int fpga_test_rtds_rtt(struct fpga *f); - -int fpga_tests(int argc, char *argv[], struct fpga *f) -{ - int ret; - - struct { - const char *name; - int (*func)(struct fpga *f); - } tests[] = { - { "Interrupt Controller", fpga_test_intc }, - { "Timer Counter", fpga_test_timer }, - { "FIFO", fpga_test_fifo }, - { "DMA", fpga_test_dma }, - { "XSG: multiply_add", fpga_test_xsg }, - { "HLS: hls_dft", fpga_test_hls_dft }, - { "RTDS: tight rtt", fpga_test_rtds_rtt } - }; - - for (int i = 0; i < ARRAY_LEN(tests); i++) { - ret = tests[i].func(f); - - info("%s: %s", tests[i].name, (ret == 0) ? GRN("passed") : RED("failed")); - } - - return 0; -} - -int fpga_test_intc(struct fpga *f) -{ - int ret; - uint32_t isr; - - if (!f->intc) - return -1; - - ret = intc_enable(f->intc, 0xFF00, 0); - if (ret) - error("Failed to enable interrupt"); - - /* Fake IRQs in software by writing to ISR */ - XIntc_Out32((uintptr_t) f->map + f->intc->baseaddr + XIN_ISR_OFFSET, 0xFF00); - - /* Wait for 8 SW triggered IRQs */ - for (int i = 0; i < 8; i++) - intc_wait(f->intc, i+8); - - /* Check ISR if all SW IRQs have been deliverd */ - isr = XIntc_In32((uintptr_t) f->map + f->intc->baseaddr + XIN_ISR_OFFSET); - - ret = intc_disable(f->intc, 0xFF00); - if (ret) - error("Failed to disable interrupt"); - - return (isr & 0xFF00) ? -1 : 0; /* ISR should get cleared by MSI_Grant_signal */ -} - -int fpga_test_xsg(struct fpga *f) -{ - int ret; - double factor, err = 0; - - struct 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); - - /* Check if required IP is available on FPGA */ - if (!dma || !xsg || !dma) - return -1; - - p = list_lookup(&xsg->model.parameters, "factor"); - if (!p) - error("Missing parameter 'factor' for model '%s'", xsg->name); - - ret = model_param_read(p, &factor); - if (ret) - error("Failed to read parameter 'factor' from model '%s'", xsg->name); - - info("Model param: factor = %f", factor); - - ret = switch_connect(f->sw, dma, xsg); - if (ret) - error("Failed to configure switch"); - ret = switch_connect(f->sw, xsg, dma); - if (ret) - error("Failed to configure switch"); - - ret = dma_alloc(dma, &mem, 0x1000, 0); - if (ret) - error("Failed to allocate DMA memory"); - - float *src = (float *) mem.base_virt; - float *dst = (float *) mem.base_virt + 0x800; - - for (int i = 0; i < 6; i++) - src[i] = 1.1 * (i+1); - - ret = dma_ping_pong(dma, (char *) src, (char *) dst, 6 * sizeof(float)); - if (ret) - error("Failed to to ping pong DMA transfer: %d", ret); - - for (int i = 0; i < 6; i++) - err += abs(factor * src[i] - dst[i]); - - info("Error after FPGA operation: err = %f", err); - - ret = switch_disconnect(f->sw, dma, xsg); - if (ret) - error("Failed to configure switch"); - ret = switch_disconnect(f->sw, xsg, dma); - if (ret) - error("Failed to configure switch"); - - ret = dma_free(dma, &mem); - if (ret) - error("Failed to release DMA memory"); - - return err > 1e-3; -} - -int fpga_test_hls_dft(struct fpga *f) -{ - int ret; - struct 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); - - /* Check if required IP is available on FPGA */ - if (!hls || !rtds) - return -1; - - ret = intc_enable(f->intc, (1 << rtds->irq), 0); - if (ret) - error("Failed to enable interrupt"); - - ret = switch_connect(f->sw, rtds, hls); - if (ret) - error("Failed to configure switch"); - ret = switch_connect(f->sw, hls, rtds); - if (ret) - error("Failed to configure switch"); - - while(1) { - /* Dump RTDS AXI Stream state */ - rtds_axis_dump(rtds); - sleep(1); - } -#if 0 - int len = 2000; - int NSAMPLES = 400; - float src[len], dst[len]; - - for (int i = 0; i < len; i++) { - src[i] = 4 + 5.0 * sin(2.0 * M_PI * 1 * i / NSAMPLES) + - 2.0 * sin(2.0 * M_PI * 2 * i / NSAMPLES) + - 1.0 * sin(2.0 * M_PI * 5 * i / NSAMPLES) + - 0.5 * sin(2.0 * M_PI * 9 * i / NSAMPLES) + - 0.2 * sin(2.0 * M_PI * 15 * i / NSAMPLES); - - fifo_write() - } -#endif - - ret = switch_disconnect(f->sw, rtds, hls); - if (ret) - error("Failed to configure switch"); - ret = switch_disconnect(f->sw, hls, rtds); - if (ret) - error("Failed to configure switch"); - - return 0; -} - -int fpga_test_fifo(struct fpga *f) -{ - int ret; - ssize_t len; - char src[255], dst[255]; - struct ip *fifo; - - fifo = ip_vlnv_lookup(&f->ips, "xilinx.com", "ip", "axi_fifo_mm_s", NULL); - if (!fifo) - return -1; - - ret = intc_enable(f->intc, (1 << fifo->irq), 0); - if (ret) - error("Failed to enable interrupt"); - - ret = switch_connect(f->sw, fifo, fifo); - if (ret) - error("Failed to configure switch"); - - /* Get some random data to compare */ - memset(dst, 0, sizeof(dst)); - ret = read_random((char *) src, sizeof(src)); - if (ret) - error("Failed to get random data"); - - len = fifo_write(fifo, (char *) src, sizeof(src)); - if (len != sizeof(src)) - error("Failed to send to FIFO"); - - len = fifo_read(fifo, (char *) dst, sizeof(dst)); - if (len != sizeof(dst)) - error("Failed to read from FIFO"); - - ret = intc_disable(f->intc, (1 << fifo->irq)); - if (ret) - error("Failed to disable interrupt"); - - ret = switch_disconnect(f->sw, fifo, fifo); - if (ret) - error("Failed to configure switch"); - - /* Compare data */ - return memcmp(src, dst, sizeof(src)); -} - -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)) - continue; /* skip non DMA IP cores */ - - /* Simple DMA can only transfer up to 4 kb due to - * PCIe page size burst limitation */ - ssize_t len = dma->dma.inst.HasSg ? 64 << 20 : 1 << 2; - - ret = dma_alloc(dma, &mem, 2 * len, 0); - if (ret) - return -1; - - ret = dma_mem_split(&mem, &src, &dst); - if (ret) - return -1; - - /* Get new random data */ - ret = read_random(src.base_virt, len); - if (ret) - serror("Failed to get random data"); - - int irq_mm2s = dma->irq; - int irq_s2mm = dma->irq + 1; - - ret = intc_enable(f->intc, (1 << irq_mm2s) | (1 << irq_s2mm), 0); - if (ret) - error("Failed to enable interrupt"); - - ret = switch_connect(f->sw, dma, dma); - if (ret) - error("Failed to configure switch"); - - /* Start transfer */ - ret = dma_ping_pong(dma, src.base_phys, dst.base_phys, dst.len); - if (ret) - error("DMA ping pong failed"); - - ret = memcmp(src.base_virt, dst.base_virt, src.len); - - info("DMA %s (%s): %s", dma->name, dma->dma.inst.HasSg ? "scatter-gather" : "simple", ret ? RED("failed") : GRN("passed")); - - ret = switch_disconnect(f->sw, dma, dma); - if (ret) - error("Failed to configure switch"); - - ret = intc_disable(f->intc, (1 << irq_mm2s) | (1 << irq_s2mm)); - if (ret) - error("Failed to disable interrupt"); - - ret = dma_free(dma, &mem); - if (ret) - error("Failed to release DMA memory"); - } - - return ret; -} - -int fpga_test_timer(struct fpga *f) -{ - int ret; - struct ip *tmr; - - tmr = ip_vlnv_lookup(&f->ips, "xilinx.com", "ip", "axi_timer", NULL); - if (!tmr) - return -1; - - XTmrCtr *xtmr = &tmr->timer.inst; - - ret = intc_enable(f->intc, (1 << tmr->irq), 0); - if (ret) - error("Failed to enable interrupt"); - - XTmrCtr_SetOptions(xtmr, 0, XTC_EXT_COMPARE_OPTION | XTC_DOWN_COUNT_OPTION); - XTmrCtr_SetResetValue(xtmr, 0, FPGA_AXI_HZ / 125); - XTmrCtr_Start(xtmr, 0); - - uint64_t counter = intc_wait(f->intc, tmr->irq); - info("Got IRQ: counter = %ju", counter); - - if (counter == 1) - return 0; - else - warn("Counter was not 1"); - - intc_disable(f->intc, (1 << tmr->irq)); - if (ret) - error("Failed to disable interrupt"); - - return -1; -} - -int fpga_test_rtds_rtt(struct fpga *f) -{ - int ret; - struct 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); - dma = list_lookup(&f->ips, "dma_1"); - - /* Check if required IP is available on FPGA */ - if (!dma || !rtds) - return -1; - - ret = switch_connect(f->sw, rtds, dma); - if (ret) - error("Failed to configure switch"); - ret = switch_connect(f->sw, dma, rtds); - if (ret) - error("Failed to configure switch"); - - ret = dma_alloc(dma, &buf, 0x100, 0); - if (ret) - error("Failed to allocate DMA memory"); - - while (1) { - - ret = dma_read(dma, buf.base_phys, buf.len); - if (ret) - error("Failed to start DMA read: %d", ret); - - ret = dma_read_complete(dma, NULL, &recvlen); - if (ret) - error("Failed to complete DMA read: %d", ret); - - ret = dma_write(dma, buf.base_phys, recvlen); - if (ret) - error("Failed to start DMA write: %d", ret); - - ret = dma_write_complete(dma, NULL, NULL); - if (ret) - error("Failed to complete DMA write: %d", ret); - } - - ret = switch_disconnect(f->sw, rtds, dma); - if (ret) - error("Failed to configure switch"); - ret = switch_disconnect(f->sw, dma, rtds); - if (ret) - error("Failed to configure switch"); - - ret = dma_free(dma, &buf); - if (ret) - error("Failed to release DMA memory"); - - return 0; -} \ No newline at end of file diff --git a/src/fpga.c b/src/fpga.c index 6de235178..98e8fca9c 100644 --- a/src/fpga.c +++ b/src/fpga.c @@ -1,109 +1,94 @@ /** VILLASfpga utility for tests and benchmarks * * @author Steffen Vogel - * @copyright 2016, Steffen Vogel + * @copyright 2017, Steffen Vogel **********************************************************************************/ #include #include -#include #include -#include #include -#include #include -#include +#include #include #include +#include #include #include #include #include +#include + #include "config.h" /* Declarations */ -int fpga_benchmarks(int argc, char *argv[], struct fpga *f); -int fpga_tests(int argc, char *argv[], struct fpga *f); +int fpga_benchmarks(int argc, char *argv[], struct fpga_card *c); -struct settings settings; - -void usage(char *name) +void usage() { - printf("Usage: %s CONFIGFILE CMD [OPTIONS]\n", name); - printf(" Commands:\n"); - printf(" tests Test functionality of VILLASfpga card\n"); - printf(" benchmarks Do benchmarks\n\n"); + printf("Usage: villas-fpga CONFIGFILE CARD [OPTIONS]\n\n"); printf(" Options:\n"); printf(" -d Set log level\n\n"); print_copyright(); - - exit(EXIT_FAILURE); } int main(int argc, char *argv[]) { int ret; - struct fpga *fpga; - config_t config; + + struct super_node sn; + struct fpga_card *card; - enum { - FPGA_TESTS, - FPGA_BENCH - } subcommand; - - if (argc < 3) - usage(argv[0]); - if (strcmp(argv[2], "tests") == 0) - subcommand = FPGA_TESTS; - else if (strcmp(argv[2], "benchmarks") == 0) - subcommand = FPGA_BENCH; - else + if (argc < 3) { usage(argv[0]); + exit(EXIT_FAILURE); + } /* Parse arguments */ char c, *endptr; while ((c = getopt(argc-1, argv+1, "d:")) != -1) { switch (c) { case 'd': - log_setlevel(strtoul(optarg, &endptr, 10), ~0); + sn.log.level = strtoul(optarg, &endptr, 10); break; case '?': default: - usage(argv[0]); + usage(); + exit(EXIT_SUCCESS); } } - info("Parsing configuration"); - cfg_parse(argv[1], &config, &settings, NULL, NULL); + super_node_init(&sn); + super_node_parse_uri(&sn, argv[1]); - info("Initialize real-time system"); - rt_init(settings.affinity, settings.priority); + log_init(&sn.log, sn.log.level, sn.log.facilities); + rt_init(sn.priority, sn.affinity); + memory_init(sn.hugepages); /* Initialize VILLASfpga card */ - config_setting_t *cfg_root = config_root_setting(&config); - ret = fpga_init(argc, argv, cfg_root); + ret = fpga_init(argc, argv, config_root_setting(&sn.cfg)); if (ret) error("Failed to initialize FPGA card"); - fpga = fpga_get(); - fpga_dump(fpga); + card = fpga_lookup_card(argv[2]); + if (!card) + error("FPGA card '%s' does not exist", argv[2]); - /* Start subcommand */ - switch (subcommand) { - case FPGA_TESTS: fpga_tests(argc-optind-1, argv+optind+1, fpga); break; - case FPGA_BENCH: fpga_benchmarks(argc-optind-1, argv+optind+1, fpga); break; - } + fpga_card_dump(card); + + /* Run benchmarks */ + fpga_benchmarks(argc-optind-1, argv+optind+1, card); /* Shutdown */ - ret = fpga_deinit(&fpga); + ret = fpga_deinit(); if (ret) - error("Failed to de-initialize fpga card"); + error("Failed to de-initialize FPGA card"); - cfg_destroy(&config); + super_node_destroy(&sn); return 0; } diff --git a/src/hook.c b/src/hook.c new file mode 100644 index 000000000..6b000a376 --- /dev/null +++ b/src/hook.c @@ -0,0 +1,185 @@ +/** Receive messages from server snd print them on stdout. + * + * @file + * @author Steffen Vogel + * @copyright 2014-2016, 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 tools Test and debug tools + * @{ + *********************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "config.h" + +config_t cfg; + +static int hook_parse_cli(struct hook *h, char *params[], int paramlen) +{ + int ret; + char *str; + config_setting_t *cfg_root; + + /* Concat all params */ + str = NULL; + for (int i = 0; i < paramlen; i++) + str = strcatf(&str, params[i]); + + config_set_auto_convert(&cfg, 1); + + if (str) { + ret = config_read_string(&cfg, str); + if (ret != CONFIG_TRUE) + error("Failed to parse argument '%s': %s", str, config_error_text(&cfg)); + } + + //config_write(&cfg, stdout); + + cfg_root = config_root_setting(&cfg); + ret = hook_parse(h, cfg_root); + + free(str); + + return ret; +} + +static void usage() +{ + printf("Usage: villas-hook [OPTIONS] NAME [PARAM] \n"); + printf(" PARAM a string of configuration settings for the hook\n"); + printf(" OPTIONS are:\n"); + printf(" -h show this help\n"); + printf(" -d LVL set debug level to LVL\n"); + printf(" -v CNT process CNT samples at once\n"); + printf(" NAME the name of the hook function\n\n"); + + printf("The following hook functions are supported:\n"); + plugin_dump(PLUGIN_TYPE_HOOK); + printf("\n"); + printf("Example:"); + printf(" villas-signal random | villas-hook skip_first seconds=10\n"); + printf("\n"); + + print_copyright(); +} + +int main(int argc, char *argv[]) +{ + int ret, level; + + size_t cnt, recv; + + /* Default values */ + level = V; + cnt = 1; + + char *name; + + struct log log; + struct plugin *p; + struct sample *samples[cnt]; + + struct pool q = { .state = STATE_DESTROYED }; + struct hook h = { .state = STATE_DESTROYED }; + + char c; + while ((c = getopt(argc, argv, "hv:d:")) != -1) { + switch (c) { + case 'v': + cnt = atoi(optarg); + break; + case 'd': + level = atoi(optarg); + break; + case 'h': + case '?': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } + } + + log_init(&log, level, LOG_ALL); + log_start(&log); + + memory_init(DEFAULT_NR_HUGEPAGES); + + if (argc < optind + 1) { + usage(); + exit(EXIT_FAILURE); + } + + if (cnt < 1) + error("Vectorize option must be greater than 0"); + + ret = pool_init(&q, 10 * cnt, SAMPLE_LEN(DEFAULT_VALUES), &memtype_hugepage); + if (ret) + error("Failed to initilize memory pool"); + + name = argv[optind]; + + p = plugin_lookup(PLUGIN_TYPE_HOOK, name); + if (!p) + error("Unknown hook function '%s'", name); + + config_init(&cfg); + + ret = hook_init(&h, &p->hook, NULL); + if (ret) + error("Failed to initialize hook"); + + ret = hook_parse_cli(&h, &argv[optind + 1], argc - optind - 1); + if (ret) + error("Failed to parse hook config"); + + hook_start(&h); + + while (!feof(stdin)) { + ret = sample_alloc(&q, samples, cnt); + if (ret != cnt) + error("Failed to allocate %zu samples from pool", cnt); + + recv = 0; + for (int j = 0; j < cnt && !feof(stdin); j++) { + ret = sample_io_villas_fscan(stdin, samples[j], NULL); + if (ret < 0) + break; + + samples[j]->ts.received = time_now(); + recv++; + } + + debug(15, "Read %zu samples from stdin", recv); + + hook_read(&h, samples, &recv); + hook_write(&h, samples, &recv); + + for (int j = 0; j < recv; j++) + sample_io_villas_fprint(stdout, samples[j], SAMPLE_IO_ALL); + fflush(stdout); + + sample_free(samples, cnt); + } + + hook_stop(&h); + hook_destroy(&h); + config_destroy(&cfg); + + sample_free(samples, cnt); + pool_destroy(&q); + + return 0; +} \ No newline at end of file diff --git a/src/node.c b/src/node.c index b3d7047c3..10bd2c645 100644 --- a/src/node.c +++ b/src/node.c @@ -1,91 +1,63 @@ /** Main routine. * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include -#include -#include #include -#include - -#include "config.h" #include -#include -#include +#include +#include #include +#include +#include +#include +#include +#include #include #include +#include +#include #ifdef ENABLE_OPAL_ASYNC - #include "opal.h" + #include #endif -struct list paths; /**< List of paths */ -struct list nodes; /**< List of nodes */ +struct super_node sn; -static config_t config; /**< libconfig handle */ -struct settings settings; /**< The global configuration */ - -static void quit() +static void quit(int signal, siginfo_t *sinfo, void *ctx) { - info("Stopping paths"); - list_foreach(struct path *p, &paths) { INDENT - path_stop(p); - } - - info("Stopping nodes"); - list_foreach(struct node *n, &nodes) { INDENT - node_stop(n); - } - - info("De-initializing node types"); - list_foreach(struct node_type *vt, &node_types) { INDENT - node_deinit(vt); - } - - /* Freeing dynamically allocated memory */ - list_destroy(&paths, (dtor_cb_t) path_destroy, false); - list_destroy(&nodes, (dtor_cb_t) node_destroy, false); - cfg_destroy(&config); + super_node_stop(&sn); + super_node_destroy(&sn); info(GRN("Goodbye!")); _exit(EXIT_SUCCESS); } -/* Setup exit handler */ -static void signals_init() -{ INDENT - struct sigaction sa_quit = { - .sa_flags = SA_SIGINFO, - .sa_sigaction = quit - }; - - sigemptyset(&sa_quit.sa_mask); - sigaction(SIGINT, &sa_quit, NULL); - sigaction(SIGTERM, &sa_quit, NULL); -} - -static void usage(const char *name) +static void usage() { - printf("Usage: %s CONFIG\n", name); - printf(" CONFIG is a required path to a configuration file\n\n"); + printf("Usage: villas-node [CONFIG]\n"); + printf(" CONFIG is the path to an optional configuration file\n"); + printf(" if omitted, VILLASnode will start without a configuration\n"); + printf(" and wait for provisioning over the web interface.\n\n"); #ifdef ENABLE_OPAL_ASYNC - printf("Usage: %s OPAL_ASYNC_SHMEM_NAME OPAL_ASYNC_SHMEM_SIZE OPAL_PRINT_SHMEM_NAME\n", name); + printf("Usage: villas-node OPAL_ASYNC_SHMEM_NAME OPAL_ASYNC_SHMEM_SIZE OPAL_PRINT_SHMEM_NAME\n"); printf(" This type of invocation is used by OPAL-RT Asynchronous processes.\n"); printf(" See in the RT-LAB User Guide for more information.\n\n"); #endif printf("Supported node types:\n"); - list_foreach(struct node_type *vt, &node_types) - printf(" - %s: %s\n", vt->name, vt->description); + plugin_dump(PLUGIN_TYPE_NODE); printf("\n"); printf("Supported hooks:\n"); - list_foreach(struct hook *h, &hooks) - printf(" - %s: %s\n", h->name, h->description); + plugin_dump(PLUGIN_TYPE_HOOK); + printf("\n"); + + printf("Supported API commands:\n"); + plugin_dump(PLUGIN_TYPE_API); printf("\n"); print_copyright(); @@ -97,76 +69,60 @@ int main(int argc, char *argv[]) { /* Check arguments */ #ifdef ENABLE_OPAL_ASYNC - if (argc != 2 && argc != 4) -#else - if (argc != 2) -#endif + if (argc != 4) usage(argv[0]); - - char *configfile = (argc == 2) ? argv[1] : "opal-shmem.conf"; - - log_init(); - info("This is VILLASnode %s (built on %s, %s)", BLD(YEL(VERSION)), + + char *uri = "opal-shmem.conf"; +#else + if (argc == 2) { + if (!strcmp(argv[1], "-h") || + !strcmp(argv[1], "--help")) + usage(); + } + else if (argc > 2) + usage(); +#endif + + info("This is VILLASnode %s (built on %s, %s)", BLD(YEL(VERSION_STR)), BLD(MAG(__DATE__)), BLD(MAG(__TIME__))); /* Checks system requirements*/ if (kernel_has_version(KERNEL_VERSION_MAJ, KERNEL_VERSION_MIN)) error("Your kernel version is to old: required >= %u.%u", KERNEL_VERSION_MAJ, KERNEL_VERSION_MIN); - /* Initialize lists */ - list_init(&paths); - list_init(&nodes); + signals_init(quit); + log_init(&sn.log, V, LOG_ALL); + log_start(&sn.log); - info("Parsing configuration"); - cfg_parse(configfile, &config, &settings, &nodes, &paths); + super_node_init(&sn); + super_node_parse_cli(&sn, argc, argv); + super_node_check(&sn); + super_node_start(&sn); - info("Initialize real-time system"); - rt_init(settings.affinity, settings.priority); + if (sn.stats > 0) + stats_print_header(); - info("Initialize signals"); - signals_init(); + struct timespec now, last = time_now(); - info("Initialize hook sub-system"); - hook_init(&nodes, &paths, &settings); + /* Run! Until signal handler is invoked */ + while (1) { + now = time_now(); + if (sn.stats > 0 && time_delta(&last, &now) > sn.stats) { + for (size_t i = 0; i < list_length(&sn.paths); i++) { + struct path *p = list_at(&sn.paths, i); - info("Initialize node types"); - list_foreach(struct node_type *vt, &node_types) { INDENT - int refs = list_length(&vt->instances); - if (refs > 0) - node_init(vt, argc, argv, config_root_setting(&config)); - } + for (size_t j = 0; j < list_length(&p->hooks); j++) { + struct hook *h = list_at(&p->hooks, j); - info("Starting nodes"); - list_foreach(struct node *n, &nodes) { INDENT - int refs = list_count(&paths, (cmp_cb_t) path_uses_node, n); - if (refs > 0) - node_start(n); - else - warn("No path is using the node %s. Skipping...", node_name(n)); - } + hook_periodic(h); + } + } - info("Starting paths"); - list_foreach(struct path *p, &paths) { INDENT - if (p->enabled) { - path_prepare(p); - path_start(p); + last = time_now(); } - else - warn("Path %s is disabled. Skipping...", path_name(p)); - } - /* Run! */ - if (settings.stats > 0) { - hook_stats_header(); - - for (;;) { - list_foreach(struct path *p, &paths) - hook_run(p, NULL, 0, HOOK_PERIODIC); - usleep(settings.stats * 1e6); - } + web_service(&sn.web); /** @todo Maybe we should move this to another thread */ } - else - pause(); return 0; } diff --git a/src/pipe.c b/src/pipe.c index b1a5d34da..8b2b99659 100644 --- a/src/pipe.c +++ b/src/pipe.c @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC * * @addtogroup tools Test and debug tools * @{ @@ -11,23 +11,21 @@ #include #include #include -#include #include #include -#include +#include #include #include #include #include #include +#include #include #include "config.h" -static struct list nodes; /**< List of all nodes */ -static struct settings settings; /**< The global configuration */ -static config_t config; +static struct super_node sn = { .state = STATE_DESTROYED }; /**< The global configuration */ struct dir { struct pool pool; @@ -47,29 +45,28 @@ static void quit(int signal, siginfo_t *sinfo, void *ctx) if (recvv.started) { pthread_cancel(recvv.thread); pthread_join(recvv.thread, NULL); + pool_destroy(&recvv.pool); } if (sendd.started) { pthread_cancel(sendd.thread); pthread_join(sendd.thread, NULL); + pool_destroy(&sendd.pool); } - - pool_destroy(&recvv.pool); - pool_destroy(&sendd.pool); + web_stop(&sn.web); node_stop(node); - node_deinit(node->_vt); + node_type_stop(node->_vt); - list_destroy(&nodes, (dtor_cb_t) node_destroy, false); - cfg_destroy(&config); + super_node_destroy(&sn); info(GRN("Goodbye!")); - exit(EXIT_SUCCESS); + _exit(EXIT_SUCCESS); } -static void usage(char *name) +static void usage() { - printf("Usage: %s CONFIG NODE [OPTIONS]\n", name); + printf("Usage: villas-pipe CONFIG NODE [OPTIONS]\n"); printf(" CONFIG path to a configuration file\n"); printf(" NODE the name of the node to which samples are sent and received from\n"); printf(" OPTIONS are:\n"); @@ -94,11 +91,11 @@ static void * send_loop(void *ctx) sendd.started = true; /* Initialize memory */ - ret = pool_init(&sendd.pool, node->vectorize, SAMPLE_LEN(DEFAULT_VALUES), &memtype_hugepage); + ret = pool_init(&sendd.pool, LOG2_CEIL(node->vectorize), SAMPLE_LEN(DEFAULT_VALUES), &memtype_hugepage); if (ret < 0) error("Failed to allocate memory for receive pool."); - ret = sample_get_many(&sendd.pool, smps, node->vectorize); + ret = sample_alloc(&sendd.pool, smps, node->vectorize); if (ret < 0) error("Failed to get %u samples out of send pool (%d).", node->vectorize, ret); @@ -107,10 +104,12 @@ static void * send_loop(void *ctx) struct sample *s = smps[i]; int reason; -retry: reason = sample_fscan(stdin, s, NULL); +retry: reason = sample_io_villas_fscan(stdin, s, NULL); if (reason < 0) { - if (feof(stdin)) + if (feof(stdin)) { + info("Reached end-of-file. Terminating..."); goto killme; + } else { warn("Skipped invalid message message: reason=%d", reason); goto retry; @@ -138,11 +137,11 @@ static void * recv_loop(void *ctx) recvv.started = true; /* Initialize memory */ - ret = pool_init(&recvv.pool, node->vectorize, SAMPLE_LEN(DEFAULT_VALUES), &memtype_hugepage); + ret = pool_init(&recvv.pool, LOG2_CEIL(node->vectorize), SAMPLE_LEN(DEFAULT_VALUES), &memtype_hugepage); if (ret < 0) error("Failed to allocate memory for receive pool."); - ret = sample_get_many(&recvv.pool, smps, node->vectorize); + ret = sample_alloc(&recvv.pool, smps, node->vectorize); if (ret < 0) error("Failed to get %u samples out of receive pool (%d).", node->vectorize, ret); @@ -159,7 +158,7 @@ static void * recv_loop(void *ctx) if (s->ts.received.tv_sec == -1 || s->ts.received.tv_sec == 0) s->ts.received = now; - sample_fprint(stdout, s, SAMPLE_ALL); + sample_io_villas_fprint(stdout, s, SAMPLE_IO_ALL); fflush(stdout); } pthread_testcancel(); @@ -170,21 +169,16 @@ static void * recv_loop(void *ctx) int main(int argc, char *argv[]) { - int ret; + int ret, level = V; char c; ptid = pthread_self(); - log_init(); - - /* Parse command line arguments */ - if (argc < 3) - usage(argv[0]); /* Default values */ sendd.enabled = true; recvv.enabled = true; - while ((c = getopt(argc-2, argv+2, "hxrsd:")) != -1) { + while ((c = getopt(argc, argv, "hxrsd:")) != -1) { switch (c) { case 'x': reverse = true; @@ -196,44 +190,48 @@ int main(int argc, char *argv[]) sendd.enabled = false; // receive only break; case 'd': - log_setlevel(atoi(optarg), -1); + level = atoi(optarg); break; case 'h': case '?': - usage(argv[0]); + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); } } + + if (argc < optind + 2) { + usage(); + exit(EXIT_FAILURE); + } - /* Setup signals */ - struct sigaction sa_quit = { - .sa_flags = SA_SIGINFO, - .sa_sigaction = quit - }; + log_init(&sn.log, level, LOG_ALL); + log_start(&sn.log); + + super_node_init(&sn); + super_node_parse_uri(&sn, argv[optind]); + + memory_init(sn.hugepages); + signals_init(quit); + rt_init(sn.priority, sn.affinity); - sigemptyset(&sa_quit.sa_mask); - sigaction(SIGTERM, &sa_quit, NULL); - sigaction(SIGINT, &sa_quit, NULL); - - /* Initialize log, configuration.. */ - list_init(&nodes); - - info("Parsing configuration"); - cfg_parse(argv[1], &config, &settings, &nodes, NULL); - - info("Initialize real-time system"); - rt_init(settings.affinity, settings.priority); + web_init(&sn.web, NULL); /* API is disabled in villas-pipe */ + web_start(&sn.web); /* Initialize node */ - node = list_lookup(&nodes, argv[2]); + node = list_lookup(&sn.nodes, argv[optind+1]); if (!node) - error("Node '%s' does not exist!", argv[2]); + error("Node '%s' does not exist!", argv[optind+1]); if (reverse) node_reverse(node); - ret = node_init(node->_vt, argc-optind, argv+optind, config_root_setting(&config)); + ret = node_type_start(node->_vt, argc, argv, config_root_setting(&sn.cfg)); if (ret) - error("Failed to intialize node: %s", node_name(node)); + error("Failed to intialize node type: %s", node_name(node)); + + ret = node_check(node); + if (ret) + error("Invalid node configuration"); ret = node_start(node); if (ret) @@ -243,8 +241,9 @@ int main(int argc, char *argv[]) pthread_create(&recvv.thread, NULL, recv_loop, NULL); pthread_create(&sendd.thread, NULL, send_loop, NULL); - for (;;) - pause(); + for (;;) { + web_service(&sn.web); + } return 0; } diff --git a/src/signal.c b/src/signal.c index 934b48ebf..aa36ff739 100644 --- a/src/signal.c +++ b/src/signal.c @@ -2,7 +2,7 @@ * * @file * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC * * @addtogroup tools Test and debug tools * @{ @@ -12,10 +12,12 @@ #include #include +#include +#include +#include +#include + #include "config.h" -#include "utils.h" -#include "sample.h" -#include "timing.h" #define CLOCKID CLOCK_REALTIME @@ -28,15 +30,17 @@ enum SIGNAL_TYPE { TYPE_MIXED }; -void usage(char *name) +void usage() { - printf("Usage: %s SIGNAL [OPTIONS]\n", name); + printf("Usage: villas-signal SIGNAL [OPTIONS]\n"); printf(" SIGNAL is on of: 'mixed', 'random', 'sine', 'triangle', 'square', 'ramp'\n"); + printf(" -d LVL set debug level\n"); printf(" -v NUM specifies how many values a message should contain\n"); printf(" -r HZ how many messages per second\n"); + printf(" -n non real-time mode. do not throttle output.\n"); printf(" -f HZ the frequency of the signal\n"); printf(" -a FLT the amplitude\n"); - printf(" -d FLT the standard deviation for 'random' signals\n"); + printf(" -D FLT the standard deviation for 'random' signals\n"); printf(" -l NUM only send LIMIT messages and stop\n\n"); print_copyright(); @@ -44,20 +48,27 @@ void usage(char *name) int main(int argc, char *argv[]) { + struct log log; + struct timespec start, now; + + enum { + MODE_RT, + MODE_NON_RT + } mode = MODE_RT; + /* Some default values */ double rate = 10; double freq = 1; double ampl = 1; double stddev = 0.02; + double running; int type = TYPE_MIXED; int values = 1; int limit = -1; - int counter; - - log_init(); + int counter, tfd, steps, level = V; if (argc < 2) { - usage(argv[0]); + usage(); exit(EXIT_FAILURE); } @@ -77,8 +88,11 @@ int main(int argc, char *argv[]) /* Parse optional command line arguments */ char c, *endptr; - while ((c = getopt(argc-1, argv+1, "hv:r:f:l:a:d:")) != -1) { + while ((c = getopt(argc-1, argv+1, "hv:r:f:l:a:D:d:n")) != -1) { switch (c) { + case 'd': + level = strtoul(optarg, &endptr, 10); + goto check; case 'l': limit = strtoul(optarg, &endptr, 10); goto check; @@ -94,12 +108,16 @@ int main(int argc, char *argv[]) case 'a': ampl = strtof(optarg, &endptr); goto check; - case 'd': + case 'D': stddev = strtof(optarg, &endptr); goto check; + case 'n': + mode = MODE_NON_RT; + break; case 'h': case '?': - usage(argv[0]); + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); } continue; @@ -108,6 +126,8 @@ check: if (optarg == endptr) error("Failed to parse parse option argument '-%c %s'", c, optarg); } + log_init(&log, level, LOG_ALL); + /* Allocate memory for message buffer */ struct sample *s = alloc(SAMPLE_LEN(values)); @@ -117,16 +137,30 @@ check: if (optarg == endptr) printf("# %-20s\t\t%s\n", "sec.nsec(seq)", "data[]"); /* Setup timer */ - int tfd = timerfd_create_rate(rate); - if (tfd < 0) - serror("Failed to create timer"); + if (mode == MODE_RT) { + tfd = timerfd_create_rate(rate); + if (tfd < 0) + serror("Failed to create timer"); + } + else + tfd = -1; - struct timespec start = time_now(); + start = time_now(); counter = 0; while (limit < 0 || counter < limit) { - struct timespec now = time_now(); - double running = time_delta(&start, &now); + if (mode == MODE_RT) { + now = time_now(); + running = time_delta(&start, &now); + } + else { + struct timespec offset; + + running = counter * 1.0 / rate; + offset = time_from_double(running); + + now = time_add(&start, &offset); + } s->ts.origin = now; s->sequence = counter; @@ -143,19 +177,25 @@ check: if (optarg == endptr) } } - sample_fprint(stdout, s, SAMPLE_ALL & ~SAMPLE_OFFSET); + sample_io_villas_fprint(stdout, s, SAMPLE_IO_ALL & ~SAMPLE_IO_OFFSET); fflush(stdout); - /* Block until 1/p->rate seconds elapsed */ - int steps = timerfd_wait(tfd); - - if (steps > 1) - warn("Missed steps: %u", steps); + /* Throttle output if desired */ + if (mode == MODE_RT) { + /* Block until 1/p->rate seconds elapsed */ + steps = timerfd_wait(tfd); + if (steps > 1) + warn("Missed steps: %u", steps); - counter += steps; + counter += steps; + } + else + counter += 1; } - close(tfd); + if (mode == MODE_RT) + close(tfd); + free(s); return 0; diff --git a/src/test-cmp.c b/src/test-cmp.c new file mode 100644 index 000000000..3f7c2f47c --- /dev/null +++ b/src/test-cmp.c @@ -0,0 +1,202 @@ +/** Compare two data files. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +void usage() +{ + printf("Usage: villas-test-cmp FILE1 FILE2 [OPTIONS]\n"); + printf(" FILE1 first file to compare\n"); + printf(" FILE2 second file to compare against\n"); + printf(" OPTIONS the following optional options:\n"); + printf(" -h print this usage information\n"); + printf(" -d LVL adjust the debug level\n"); + printf(" -j return the results as a JSON object\n"); + printf(" -m return the results as a MATLAB struct\n"); + printf(" -e EPS set epsilon for floating point comparisons to EPS\n"); + printf(" -l LOW smallest value for histogram\n"); + printf(" -H HIGH largest value for histogram\n"); + printf(" -r RES bucket resolution for histogram\n"); + printf("\n"); + + print_copyright(); +} + +int main(int argc, char *argv[]) +{ + int ret = 0; + double epsilon = 1e-9; + + /* Histogram */ + double low = 0; /**< Lowest value in histogram. */ + double high = 1e-1; /**< Highest value in histogram. */ + double res = 1e-3; /**< Histogram resolution. */ + + enum { + OUTPUT_JSON, + OUTPUT_MATLAB, + OUTPUT_HUMAN + } output = OUTPUT_HUMAN; + + struct log log; + struct pool pool = { .state = STATE_DESTROYED }; + struct hist hist; + struct sample *samples[2]; + + struct { + int flags; + char *path; + FILE *handle; + struct sample *sample; + } f1, f2; + + /* Parse Arguments */ + char c, *endptr; + while ((c = getopt (argc, argv, "hjmd:e:l:H:r:")) != -1) { + switch (c) { + case 'd': + log.level = strtoul(optarg, &endptr, 10); + goto check; + case 'e': + epsilon = strtod(optarg, &endptr); + goto check; + case 'j': + output = OUTPUT_JSON; + break; + case 'm': + output = OUTPUT_MATLAB; + break; + case 'l': + low = strtod(optarg, &endptr); + goto check; + case 'H': + high = strtod(optarg, &endptr); + goto check; + case 'r': + res = strtod(optarg, &endptr); + goto check; + case 'h': + case '?': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } + + continue; + +check: if (optarg == endptr) + error("Failed to parse parse option argument '-%c %s'", c, optarg); + } + + if (argc < optind + 2) { + usage(); + exit(EXIT_FAILURE); + } + + f1.path = argv[optind]; + f2.path = argv[optind + 1]; + + log_init(&log, V, LOG_ALL); + log_start(&log); + + hist_init(&hist, low, high, res); + pool_init(&pool, 1024, SAMPLE_LEN(DEFAULT_VALUES), &memtype_heap); + sample_alloc(&pool, samples, 2); + + f1.sample = samples[0]; + f2.sample = samples[1]; + + f1.handle = fopen(f1.path, "r"); + if (!f1.handle) + serror("Failed to open file: %s", f1.path); + + f2.handle = fopen(f2.path, "r"); + if (!f2.handle) + serror("Failed to open file: %s", f2.path); + + while (!feof(f1.handle) && !feof(f2.handle)) { + ret = sample_io_villas_fscan(f1.handle, f1.sample, &f1.flags); + if (ret < 0) { + if (feof(f1.handle)) + ret = 0; + goto out; + } + + ret = sample_io_villas_fscan(f2.handle, f2.sample, &f2.flags); + if (ret < 0) { + if (feof(f2.handle)) + ret = 0; + goto out; + } + + /* Compare sequence no */ + if ((f1.flags & SAMPLE_IO_SEQUENCE) && (f2.flags & SAMPLE_IO_SEQUENCE)) { + if (f1.sample->sequence != f2.sample->sequence) { + printf("sequence no: %d != %d\n", f1.sample->sequence, f2.sample->sequence); + ret = -1; + goto out; + } + } + + /* Compare timestamp */ + if (time_delta(&f1.sample->ts.origin, &f2.sample->ts.origin) > epsilon) { + printf("ts.origin: %f != %f\n", time_to_double(&f1.sample->ts.origin), time_to_double(&f2.sample->ts.origin)); + ret = -2; + goto out; + } + + /* Collect historgram info of offset */ + hist_put(&hist, time_delta(&f1.sample->ts.origin, &f2.sample->ts.received)); + + /* Compare data */ + if (f1.sample->length != f2.sample->length) { + printf("length: %d != %d\n", f1.sample->length, f2.sample->length); + ret = -3; + goto out; + } + + for (int i = 0; i < f1.sample->length; i++) { + if (fabs(f1.sample->data[i].f - f2.sample->data[i].f) > epsilon) { + printf("data[%d]: %f != %f\n", i, f1.sample->data[i].f, f2.sample->data[i].f); + ret = -4; + goto out; + } + } + } + +out: sample_free(samples, 2); + + fclose(f1.handle); + fclose(f2.handle); + + switch (output) { + case OUTPUT_MATLAB: + hist_dump_matlab(&hist, stdout); + break; + case OUTPUT_JSON: + hist_dump_json(&hist, stdout); + break; + case OUTPUT_HUMAN: + hist_print(&hist, 1); + break; + } + + hist_destroy(&hist); + pool_destroy(&pool); + + return ret; +} \ No newline at end of file diff --git a/src/test.c b/src/test-rtt.c similarity index 64% rename from src/test.c rename to src/test-rtt.c index d1288b883..af523335f 100644 --- a/src/test.c +++ b/src/test-rtt.c @@ -1,7 +1,7 @@ -/** Some basic tests. +/** Measure round-trip time. * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include @@ -11,17 +11,17 @@ #include #include -#include "config.h" -#include "cfg.h" -#include "msg.h" -#include "node.h" -#include "utils.h" -#include "hist.h" -#include "timing.h" -#include "pool.h" +#include +#include +#include +#include +#include +#include +#include -struct settings settings; /** _vt, argc-3, argv+3, config_root_setting(&config)); + node_type_start(node->_vt, argc-3, argv+3, config_root_setting(&sn.cfg)); node_start(node); /* Parse Arguments */ char c, *endptr; - while ((c = getopt (argc-3, argv+3, "l:h:r:f:c:")) != -1) { + while ((c = getopt (argc-3, argv+3, "l:hH:r:f:c:")) != -1) { switch (c) { case 'c': count = strtoul(optarg, &endptr, 10); @@ -105,22 +104,16 @@ int main(int argc, char *argv[]) case 'l': low = strtod(optarg, &endptr); goto check; - case 'h': + case 'H': high = strtod(optarg, &endptr); goto check; case 'r': res = strtod(optarg, &endptr); goto check; + case 'h': case '?': - if (optopt == 'c') - error("Option -%c requires an argument.", optopt); - else if (isprint(optopt)) - error("Unknown option '-%c'.", optopt); - else - error("Unknown option character '\\x%x'.", optopt); - exit(EXIT_FAILURE); - default: - abort(); + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); } continue; @@ -129,16 +122,12 @@ check: if (optarg == endptr) error("Failed to parse parse option argument '-%c %s'", c, optarg); } - if (!strcmp(argv[2], "rtt")) - test_rtt(); - else - error("Unknown test: '%s'", argv[2]); + test_rtt(); node_stop(node); - node_deinit(node->_vt); + node_type_stop(node->_vt); - list_destroy(&nodes, (dtor_cb_t) node_destroy, false); - cfg_destroy(&config); + super_node_destroy(&sn); return 0; } @@ -151,7 +140,7 @@ void test_rtt() { struct sample *smp_send = alloc(SAMPLE_LEN(2)); struct sample *smp_recv = alloc(SAMPLE_LEN(2)); - hist_create(&hist, low, high, res); + hist_init(&hist, low, high, res); /* Print header */ fprintf(stdout, "%17s%5s%10s%10s%10s%10s%10s\n", "timestamp", "seq", "rtt", "min", "max", "mean", "stddev"); @@ -182,12 +171,12 @@ void test_rtt() { struct stat st; if (!fstat(fd, &st)) { FILE *f = fdopen(fd, "w"); - hist_matlab(&hist, f); + hist_dump_matlab(&hist, f); } else error("Invalid file descriptor: %u", fd); - hist_print(&hist); + hist_print(&hist, 1); hist_destroy(&hist); } diff --git a/tests/Makefile.inc b/tests/Makefile.inc index 9bac51525..dad98fc1d 100644 --- a/tests/Makefile.inc +++ b/tests/Makefile.inc @@ -1,32 +1,10 @@ -TEST_SRCS = $(wildcard tests/*.c) -TEST_OBJS = $(patsubst %.c,$(BUILDDIR)/%.o,$(TEST_SRCS)) +-include tests/unit/Makefile.inc -TEST_CFLAGS = $(CFLAGS) -TEST_LDFLAGS = $(LDFLAGS) -Wl,-rpath,'$$ORIGIN' -TEST_LDLIBS = $(LDLIBS) -lcriterion -lvillas -pthread +tests: unit-tests -tests: $(BUILDDIR)/testsuite - -run-tests: tests - echo 25 > /proc/sys/vm/nr_hugepages - $(BUILDDIR)/testsuite - -# Compile -$(BUILDDIR)/tests/%.o: tests/%.c | $$(dir $$@) - $(CC) $(TEST_CFLAGS) -c $< -o $@ - -# Link -$(BUILDDIR)/testsuite: $(TEST_OBJS) | $(LIBS) - $(CC) $(TEST_LDFLAGS) $(TEST_LDLIBS) $^ -o $@ - -ifdef COVERAGE --include tests/Makefile.gcov.inc -endif - -# Tests are not installed -install-tests: +run-tests: run-unit-tests run-integration-tests -clean-tests: - rm -rf $(BUILDDIR)/tests $(BUILDDIR)/testsuite +run-integration-tests: src tools + @$(SRCDIR)/tests/integration-tests.sh -.PHONY: tests install-tests clean-tests run-tests \ No newline at end of file +.PHONY: tests run-tests run-integration-tests diff --git a/tests/integration-tests.sh b/tests/integration-tests.sh new file mode 100755 index 000000000..c91e15f54 --- /dev/null +++ b/tests/integration-tests.sh @@ -0,0 +1,81 @@ +#!/bin/bash +# +# Run integration tests +# +# @author Steffen Vogel +# @copyright 2017, Institute for Automation of Complex Power Systems, EONERC +################################################################################## + +SCRIPT=$(realpath ${BASH_SOURCE[0]}) +SCRIPTPATH=$(dirname $SCRIPT) + +export SRCDIR=$(realpath ${SCRIPTPATH}/..) +export BUILDDIR=${SRCDIR}/build/release +export LOGDIR=${BUILDDIR}/tests/integration +export PATH=${BUILDDIR}:${PATH} + +# Default values +VERBOSE=0 +FILTER='*' + +export NUM_SAMPLES=100 + +# Parse command line arguments +while getopts ":f:v" OPT; do + case ${OPT} in + f) + FILTER=${OPTARG} + ;; + v) + VERBOSE=1 + ;; + \?) + echo "Invalid option: -${OPTARG}" >&2 + ;; + :) + echo "Option -$OPTARG requires an argument." >&2 + exit 1 + ;; + esac +done + +TESTS=${SRCDIR}/tests/integration/${FILTER}.sh + +# Preperations +mkdir -p ${LOGDIR} + +NUM_PASS=0 +NUM_FAIL=0 + +# Preamble +echo -e "Starting integration tests for VILLASnode/fpga:\n" + +for TEST in ${TESTS}; do + TESTNAME=$(basename -s .sh ${TEST}) + + # Run test + if (( ${VERBOSE} == 0 )); then + ${TEST} &> ${LOGDIR}/${TESTNAME}.log + else + ${TEST} + fi + + RC=$? + + if (( $RC != 0 )); then + echo -e "\e[31m[Fail] \e[39m ${TESTNAME} with code $RC" + NUM_FAIL=$((${NUM_FAIL} + 1)) + else + echo -e "\e[32m[Pass] \e[39m ${TESTNAME}" + NUM_PASS=$((${NUM_PASS} + 1)) + fi +done + +# Show summary +if (( ${NUM_FAIL} > 0 )); then + echo -e "\nSummary: ${NUM_FAIL} of $((${NUM_FAIL} + ${NUM_PASS})) tests failed." + exit 1 +else + echo -e "\nSummary: all tests passed!" + exit 0 +fi \ No newline at end of file diff --git a/tests/integration/api-config.sh b/tests/integration/api-config.sh new file mode 100755 index 000000000..72fd5d0dd --- /dev/null +++ b/tests/integration/api-config.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +LOCAL_CONF=${SRCDIR}/etc/loopback.conf +FETCHED_CONF=$(mktemp) + +echo ${CONF} + +# Start VILLASnode instance with local config (via advio) +villas-node file://${LOCAL_CONF} & + +sleep 1 + +# Fetch config via API +curl -sX POST --data '{ "command" : "config" }' http://localhost/api/v1 2>/dev/null > ${FETCHED_CONF} + +# Shutdown VILLASnode +kill $! + +# Compare local config with the fetched one +diff -u <(cat ${LOCAL_CONF} | conf2json | jq -S .) <(cat ${FETCHED_CONF} | jq -S .config) + +RC=$? + +rm -f ${FETCHED_CONF} + +exit $RC \ No newline at end of file diff --git a/tests/integration/hook-convert.sh b/tests/integration/hook-convert.sh new file mode 100755 index 000000000..95efd850e --- /dev/null +++ b/tests/integration/hook-convert.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +INPUT_FILE=$(mktemp) +OUTPUT_FILE=$(mktemp) +EXPECT_FILE=$(mktemp) + +cat < ${INPUT_FILE} +1490500399.776379108(0) 0.000000 0.000000 0.000000 0.000000 +1490500399.876379108(1) 0.587785 0.587785 0.587785 0.587785 +1490500399.976379108(2) 0.951057 0.951057 0.951057 0.951057 +1490500400.076379108(3) 0.951057 0.951057 0.951057 0.951057 +1490500400.176379108(4) 0.587785 0.587785 0.587785 0.587785 +1490500400.276379108(5) 0.000000 0.000000 0.000000 0.000000 +1490500400.376379108(6) -0.587785 -0.587785 -0.587785 -0.587785 +1490500400.476379108(7) -0.951057 -0.951057 -0.951057 -0.951057 +1490500400.576379108(8) -0.951057 -0.951057 -0.951057 -0.951057 +1490500400.676379108(9) -0.587785 -0.587785 -0.587785 -0.587785 +EOF + +cat < ${EXPECT_FILE} +1490500399.776379108(0) 0.000000 0 0 0.000000 +1490500399.876379108(1) 0.587785 58 58 0.587785 +1490500399.976379108(2) 0.951057 95 95 0.951057 +1490500400.076379108(3) 0.951057 95 95 0.951057 +1490500400.176379108(4) 0.587785 58 58 0.587785 +1490500400.276379108(5) 0.000000 0 0 0.000000 +1490500400.376379108(6) -0.587785 -58 -58 -0.587785 +1490500400.476379108(7) -0.951057 -95 -95 -0.951057 +1490500400.576379108(8) -0.951057 -95 -95 -0.951057 +1490500400.676379108(9) -0.587785 -58 -58 -0.587785 +EOF + +villas-hook convert 'mode="fixed" scale=100 mask=0x6' < ${INPUT_FILE} > ${OUTPUT_FILE} + +# Compare only the data values +diff -u <(cut -f2- ${OUTPUT_FILE}) <(cut -f2- ${EXPECT_FILE}) + +RC=$? + +rm -f ${INPUT_FILE} ${OUTPUT_FILE} ${EXPECT_FILE} + +exit $RC \ No newline at end of file diff --git a/tests/integration/hook-decimate.sh b/tests/integration/hook-decimate.sh new file mode 100755 index 000000000..a62c7f0a1 --- /dev/null +++ b/tests/integration/hook-decimate.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +INPUT_FILE=$(mktemp) +OUTPUT_FILE=$(mktemp) +EXPECT_FILE=$(mktemp) + +cat < ${INPUT_FILE} +1490500399.776379108(0) 0.000000 0.000000 0.000000 0.000000 +1490500399.876379108(1) 0.587785 0.587785 0.587785 0.587785 +1490500399.976379108(2) 0.951057 0.951057 0.951057 0.951057 +1490500400.076379108(3) 0.951057 0.951057 0.951057 0.951057 +1490500400.176379108(4) 0.587785 0.587785 0.587785 0.587785 +1490500400.276379108(5) 0.000000 0.000000 0.000000 0.000000 +1490500400.376379108(6) -0.587785 -0.587785 -0.587785 -0.587785 +1490500400.476379108(7) -0.951057 -0.951057 -0.951057 -0.951057 +1490500400.576379108(8) -0.951057 -0.951057 -0.951057 -0.951057 +1490500400.676379108(9) -0.587785 -0.587785 -0.587785 -0.587785 +EOF + +cat < ${EXPECT_FILE} +1490500399.776379108(0) 0.000000 0.000000 0.000000 0.000000 +1490500400.076379108(3) 0.951057 0.951057 0.951057 0.951057 +1490500400.376379108(6) -0.587785 -0.587785 -0.587785 -0.587785 +1490500400.676379108(9) -0.587785 -0.587785 -0.587785 -0.587785 +EOF + +villas-hook decimate 'ratio=3' < ${INPUT_FILE} > ${OUTPUT_FILE} + +# Compare only the data values +diff -u <(cut -f2- ${OUTPUT_FILE}) <(cut -f2- ${EXPECT_FILE}) + +RC=$? + +rm -f ${INPUT_FILE} ${OUTPUT_FILE} ${EXPECT_FILE} + +exit $RC \ No newline at end of file diff --git a/tests/integration/hook-drop.sh b/tests/integration/hook-drop.sh new file mode 100755 index 000000000..d18e2a8c3 --- /dev/null +++ b/tests/integration/hook-drop.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +INPUT_FILE=$(mktemp) +OUTPUT_FILE=$(mktemp) +EXPECT_FILE=$(mktemp) + +cat < ${INPUT_FILE} +1490500399.776379108(0) 0.000000 0.000000 0.000000 0.000000 +1490500399.876379108(1) 0.587785 0.587785 0.587785 0.587785 +1490500399.976379108(2) 0.951057 0.951057 0.951057 0.951057 +1490500399.976379108(2) 0.951057 0.951057 0.951057 0.951057 +1490500399.976379108(2) 0.951057 0.951057 0.951057 0.951057 +1490500400.076379108(3) 0.951057 0.951057 0.951057 0.951057 +1490500400.176379108(4) 0.587785 0.587785 0.587785 0.587785 +1490500400.476379108(7) -0.951057 -0.951057 -0.951057 -0.951057 +1490500400.276379108(5) 0.000000 0.000000 0.000000 0.000000 +1490500400.576379108(8) -0.951057 -0.951057 -0.951057 -0.951057 +1490500400.376379108(6) -0.587785 -0.587785 -0.587785 -0.587785 +1490500400.676379108(9) -0.587785 -0.587785 -0.587785 -0.587785 +EOF + +cat < ${EXPECT_FILE} +1490500399.776379108(0) 0.000000 0.000000 0.000000 0.000000 +1490500399.876379108(1) 0.587785 0.587785 0.587785 0.587785 +1490500399.976379108(2) 0.951057 0.951057 0.951057 0.951057 +1490500400.076379108(3) 0.951057 0.951057 0.951057 0.951057 +1490500400.176379108(4) 0.587785 0.587785 0.587785 0.587785 +1490500400.476379108(7) -0.951057 -0.951057 -0.951057 -0.951057 +1490500400.576379108(8) -0.951057 -0.951057 -0.951057 -0.951057 +1490500400.676379108(9) -0.587785 -0.587785 -0.587785 -0.587785 +EOF + +villas-hook drop < ${INPUT_FILE} > ${OUTPUT_FILE} + +# Compare only the data values +diff -u <(cut -f2- ${OUTPUT_FILE}) <(cut -f2- ${EXPECT_FILE}) + +RC=$? + +rm -f ${INPUT_FILE} ${OUTPUT_FILE} ${EXPECT_FILE} + +exit $RC \ No newline at end of file diff --git a/tests/integration/hook-map.sh b/tests/integration/hook-map.sh new file mode 100755 index 000000000..c46b75498 --- /dev/null +++ b/tests/integration/hook-map.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +INPUT_FILE=$(mktemp) +OUTPUT_FILE=$(mktemp) +EXPECT_FILE=$(mktemp) + +cat < ${INPUT_FILE} +1490500399.776379108(0) 0.000000 0.000000 0.000000 0.000000 +1490500399.876379108(1) 0.587785 0.587785 0.587785 0.587785 +1490500399.976379108(2) 0.951057 0.951057 0.951057 0.951057 +1490500400.076379108(3) 0.951057 0.951057 0.951057 0.951057 +1490500400.176379108(4) 0.587785 0.587785 0.587785 0.587785 +1490500400.276379108(5) 0.000000 0.000000 0.000000 0.000000 +1490500400.376379108(6) -0.587785 -0.587785 -0.587785 -0.587785 +1490500400.476379108(7) -0.951057 -0.951057 -0.951057 -0.951057 +1490500400.576379108(8) -0.951057 -0.951057 -0.951057 -0.951057 +1490500400.676379108(9) -0.587785 -0.587785 -0.587785 -0.587785 +EOF + +cat < ${EXPECT_FILE} +1490500399.776379108(0) 0.000000 0 1490500399 776379108 0.000000 0.000000 +1490500399.876379108(1) 0.587785 1 1490500399 876379108 0.587785 0.587785 +1490500399.976379108(2) 0.951057 2 1490500399 976379108 0.951057 0.951057 +1490500400.076379108(3) 0.951057 3 1490500400 76379108 0.951057 0.951057 +1490500400.176379108(4) 0.587785 4 1490500400 176379108 0.587785 0.587785 +1490500400.276379108(5) 0.000000 5 1490500400 276379108 0.000000 0.000000 +1490500400.376379108(6) -0.587785 6 1490500400 376379108 -0.587785 -0.587785 +1490500400.476379108(7) -0.951057 7 1490500400 476379108 -0.951057 -0.951057 +1490500400.576379108(8) -0.951057 8 1490500400 576379108 -0.951057 -0.951057 +1490500400.676379108(9) -0.587785 9 1490500400 676379108 -0.587785 -0.587785 +EOF + +villas-hook map 'mapping = [ "data[3]", "hdr.sequence", "ts.origin", "data[1-2]" ]' < ${INPUT_FILE} > ${OUTPUT_FILE} + +# Compare only the data values +diff -u <(cut -f2- ${OUTPUT_FILE}) <(cut -f2- ${EXPECT_FILE}) + +RC=$? + +rm -f ${INPUT_FILE} ${OUTPUT_FILE} ${EXPECT_FILE} + +exit $RC \ No newline at end of file diff --git a/tests/integration/hook-shift_seq.sh b/tests/integration/hook-shift_seq.sh new file mode 100755 index 000000000..6662a22de --- /dev/null +++ b/tests/integration/hook-shift_seq.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +OUTPUT_FILE=$(mktemp) + +OFFSET=100 + +villas-signal random -l ${NUM_SAMPLES} -n | villas-hook shift_seq offset=${OFFSET} > ${OUTPUT_FILE} + +# Compare shifted sequence no +diff -u \ + <(sed -re 's/^[0-9]+\.[0-9]+([\+\-][0-9]+\.[0-9]+(e[\+\-][0-9]+)?)?\(([0-9]+)\).*/\3/g' ${OUTPUT_FILE}) \ + <(seq ${OFFSET} $((${NUM_SAMPLES}+${OFFSET}-1))) + +RC=$? + +rm -f ${OUTPUT_FILE} + +exit $RC diff --git a/tests/integration/hook-shift_ts.sh b/tests/integration/hook-shift_ts.sh new file mode 100755 index 000000000..132f40570 --- /dev/null +++ b/tests/integration/hook-shift_ts.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +STATS_FILE=$(mktemp) + +OFFSET=10 +EPSILON=0.05 + +villas-signal sine -l 10 -r 10 | villas-hook shift_ts offset=${OFFSET} | villas-hook stats format=\"json\" output=\"${STATS_FILE}\" > /dev/null + +#jq .owd ${STATS_FILE} + +jq -e ".owd.mean - ${OFFSET} | length < ${EPSILON}" ${STATS_FILE} > /dev/null + +RC=$? + +rm ${STATS_FILE} + +exit $RC \ No newline at end of file diff --git a/tests/integration/hook-skip_first.sh b/tests/integration/hook-skip_first.sh new file mode 100755 index 000000000..f74751af9 --- /dev/null +++ b/tests/integration/hook-skip_first.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +OUTPUT_FILE=$(mktemp) + +SKIP=10 + +echo ${OUTPUT_FILE} + +villas-signal random -r 1 -l ${NUM_SAMPLES} -n | villas-hook skip_first seconds=${SKIP} > ${OUTPUT_FILE} + +LINES=$(wc -l < ${OUTPUT_FILE}) + +rm ${OUTPUT_FILE} + +# Test condition +(( ${LINES} == ${NUM_SAMPLES} - ${SKIP} )) \ No newline at end of file diff --git a/tests/integration/hook-skip_first2.sh b/tests/integration/hook-skip_first2.sh new file mode 100755 index 000000000..5986b5548 --- /dev/null +++ b/tests/integration/hook-skip_first2.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +OUTPUT_FILE=$(mktemp) + +SKIP=50 + +villas-signal random -r 1 -l ${NUM_SAMPLES} -n | villas-hook skip_first samples=${SKIP} > ${OUTPUT_FILE} + +LINES=$(wc -l < ${OUTPUT_FILE}) + +rm ${OUTPUT_FILE} + +# Test condition +(( ${LINES} == ${NUM_SAMPLES} - ${SKIP} )) \ No newline at end of file diff --git a/tests/Makefile.gcov.inc b/tests/unit/Makefile.gcov.inc similarity index 96% rename from tests/Makefile.gcov.inc rename to tests/unit/Makefile.gcov.inc index c8833625e..4d1a3e7f1 100644 --- a/tests/Makefile.gcov.inc +++ b/tests/unit/Makefile.gcov.inc @@ -1,4 +1,4 @@ -COVERAGE_TESTS = $(BUILDDIR)/testsuite +COVERAGE_TESTS = $(BUILDDIR)/unit-tests COVERAGE_OBJS = $(LIB_OBJS) $(SRC_OBJS) GCDAS = $(COVERAGE_OBJS:.o=.gcda) diff --git a/tests/unit/Makefile.inc b/tests/unit/Makefile.inc new file mode 100644 index 000000000..98b54dd77 --- /dev/null +++ b/tests/unit/Makefile.inc @@ -0,0 +1,31 @@ +TEST_SRCS = $(wildcard tests/unit/*.c) +TEST_OBJS = $(patsubst %.c,$(BUILDDIR)/%.o,$(TEST_SRCS)) + +TEST_CFLAGS = $(CFLAGS) +TEST_LDFLAGS = $(LDFLAGS) -Wl,-rpath,'$$ORIGIN' +TEST_LDLIBS = $(LDLIBS) -lcriterion -lvillas -pthread -ljansson + +unit-tests: $(BUILDDIR)/unit-tests + +run-unit-tests: tests + $(BUILDDIR)/unit-tests + +# Compile +$(BUILDDIR)/tests/unit/%.o: tests/unit/%.c | $$(dir $$@) + $(CC) $(TEST_CFLAGS) -c $< -o $@ + +# Link +$(BUILDDIR)/unit-tests: $(TEST_OBJS) | $(LIBS) + $(CC) $(TEST_LDFLAGS) $(TEST_LDLIBS) $^ -o $@ + +ifdef COVERAGE +-include tests/Makefile.gcov.inc +endif + +# Tests are not installed +install-tests: + +clean-tests: + rm -rf $(BUILDDIR)/tests $(BUILDDIR)/testsuite + +.PHONY: unit-tests install-unit-tests clean-unit-tests run-unit-tests \ No newline at end of file diff --git a/tests/unit/advio.c b/tests/unit/advio.c new file mode 100644 index 000000000..83ae02148 --- /dev/null +++ b/tests/unit/advio.c @@ -0,0 +1,128 @@ +/** Unit tests for advio + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#include + +#include +#include + +#include +#include + +/** This URI points to a Sciebo share which contains some test files. + * The Sciebo share is read/write accessible via WebDAV. */ +#define BASE_URI "https://1Nrd46fZX8HbggT:badpass@rwth-aachen.sciebo.de/public.php/webdav/node/tests" + +Test(advio, download) +{ + AFILE *af; + int ret; + size_t len; + char buffer[64]; + char expect[64] = "ook4iekohC2Teegoghu6ayoo1OThooregheebaet8Zod1angah0che7quai4ID7A"; + + af = afopen(BASE_URI "/download" , "r"); + cr_assert(af, "Failed to download file"); + + len = afread(buffer, 1, sizeof(buffer), af); + cr_assert_gt(len, 0, "len=%zu, feof=%u", len, afeof(af)); + + cr_assert_arr_eq(buffer, expect, sizeof(expect)); + + ret = afclose(af); + cr_assert_eq(ret, 0, "Failed to close file"); +} + +Test(advio, upload) +{ + AFILE *af; + int ret; + size_t len; + + char upload[64]; + char buffer[64]; + + /* Get some random data to upload */ + len = read_random(upload, sizeof(upload)); + cr_assert_eq(len, sizeof(upload)); + + /* Open file for writing */ + af = afopen(BASE_URI "/upload", "w+"); + cr_assert(af, "Failed to download file"); + + len = afwrite(upload, 1, sizeof(upload), af); + cr_assert_eq(len, sizeof(upload)); + + ret = afclose(af); + cr_assert_eq(ret, 0, "Failed to close/upload file"); + + /* Open for reading and comparison */ + af = afopen(BASE_URI "/upload", "r"); + cr_assert(af, "Failed to download file"); + + len = afread(buffer, 1, sizeof(upload), af); + cr_assert_eq(len, sizeof(upload)); + + cr_assert_arr_eq(buffer, upload, len); + + ret = afclose(af); + cr_assert(ret == 0, "Failed to close file"); +} + +Test(advio, append) +{ + AFILE *af; + int ret; + size_t len; + + char append1[64] = "xa5gieTohlei9iu1uVaePae6Iboh3eeheeme5iejue5sheshae4uzisha9Faesei"; + char append2[64] = "bitheeRae7igee2miepahJaefoGad1Ooxeif0Mooch4eojoumueYahn4ohc9poo2"; + char expect[128] = "xa5gieTohlei9iu1uVaePae6Iboh3eeheeme5iejue5sheshae4uzisha9FaeseibitheeRae7igee2miepahJaefoGad1Ooxeif0Mooch4eojoumueYahn4ohc9poo2"; + char buffer[128]; + + /* Open file for writing first chunk */ + af = afopen(BASE_URI "/append", "w+"); + cr_assert(af, "Failed to download file"); + + /* The append file might already exist and be not empty from a previous run. */ + ret = ftruncate(afileno(af), 0); + cr_assert_eq(ret, 0); + + char c; + fseek(af->file, 0, SEEK_SET); + if (af->file) { + while ((c = getc(af->file)) != EOF) + putchar(c); + } + + len = afwrite(append1, 1, sizeof(append1), af); + cr_assert_eq(len, sizeof(append1)); + + ret = afclose(af); + cr_assert_eq(ret, 0, "Failed to close/upload file"); + + /* Open file for writing second chunk */ + af = afopen(BASE_URI "/append", "a"); + cr_assert(af, "Failed to download file"); + + len = afwrite(append2, 1, sizeof(append2), af); + cr_assert_eq(len, sizeof(append2)); + + ret = afclose(af); + cr_assert_eq(ret, 0, "Failed to close/upload file"); + + /* Open for reading and comparison */ + af = afopen(BASE_URI "/append", "r"); + cr_assert(af, "Failed to download file"); + + len = afread(buffer, 1, sizeof(buffer), af); + cr_assert_eq(len, sizeof(buffer)); + + ret = afclose(af); + cr_assert(ret == 0, "Failed to close file"); + + cr_assert_arr_eq(buffer, expect, sizeof(expect)); +} \ No newline at end of file diff --git a/tests/unit/config_json.c b/tests/unit/config_json.c new file mode 100644 index 000000000..10c67ff32 --- /dev/null +++ b/tests/unit/config_json.c @@ -0,0 +1,99 @@ +/** Unit tests libconfig to jansson converters. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#include + +#include +#include + +#include "utils.h" + +const char *cfg_example = "test : \n" + "{\n" + " hallo = 1L;\n" + "};\n" + "liste = ( 1.1, 2L, 3L, 4L, \n" + " {\n" + " objekt : \n" + " {\n" + " key = \"value\";\n" + " };\n" + " } );\n"; + +const char *json_example = "{\n" + " \"test\": {\n" + " \"hallo\": 1\n" + " },\n" + " \"liste\": [\n" + " 1.1000000000000001,\n" + " 2,\n" + " 3,\n" + " 4,\n" + " {\n" + " \"objekt\": {\n" + " \"key\": \"value\"\n" + " }\n" + " }\n" + " ]\n" + "}"; + +Test(utils, config_to_json) +{ + int ret; + config_t cfg; + config_setting_t *cfg_root; + json_t *json; + + config_init(&cfg); + + ret = config_read_string(&cfg, cfg_example); + cr_assert_eq(ret, CONFIG_TRUE); + + cfg_root = config_root_setting(&cfg); + + json = config_to_json(cfg_root); + cr_assert_not_null(json); + + char *str = json_dumps(json, JSON_INDENT(2)); + + //printf("%s\n", str); + + json_decref(json); + + cr_assert_str_eq(str, json_example); + + config_destroy(&cfg); +} + +Test(utils, json_to_config) +{ + config_t cfg; + config_setting_t *cfg_root; + json_t *json; + + /* For config_write() */ + FILE *f; + char str[1024]; + + config_init(&cfg); + + cfg_root = config_root_setting(&cfg); + + json = json_loads(json_example, 0, NULL); + cr_assert_not_null(json); + + json_to_config(json, cfg_root); + + //config_write(&cfg, stdout); + + f = fmemopen(str, sizeof(str), "w+"); + config_write(&cfg, f); + fclose(f); + + cr_assert_str_eq(str, cfg_example); + + json_decref(json); +} \ No newline at end of file diff --git a/tests/unit/fpga.c b/tests/unit/fpga.c new file mode 100644 index 000000000..fed0dab65 --- /dev/null +++ b/tests/unit/fpga.c @@ -0,0 +1,401 @@ +/** Test procedures for VILLASfpga + * + * @author Steffen Vogel + * @copyright 2017, Steffen Vogel + *********************************************************************************/ + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "config.h" + +#define TEST_CONFIG "/villas/etc/fpga.conf" +#define TEST_LEN 0x1000 + +#define CPU_HZ 3392389000 + +static struct fpga_card *card; +static struct super_node sn = { .state = STATE_DESTROYED }; +static struct pci pci; +static struct vfio_container vc; + +static void init() +{ + int ret; + config_setting_t *cfg_root; + + ret = super_node_init(&sn); + cr_assert_eq(ret, 0, "Failed to initialize Supernode"); + + ret = super_node_parse_uri(&sn, TEST_CONFIG); + cr_assert_eq(ret, 0, "Failed to parse configuration"); + + ret = super_node_check(&sn); + cr_assert_eq(ret, 0, "Failed to check configuration"); + + cfg_root = config_root_setting(&sn.cfg); + cr_assert_neq(cfg_root, NULL); + + ret = pci_init(&pci); + cr_assert_eq(ret, 0, "Failed to initialize PCI sub-system"); + + ret = vfio_init(&vc); + cr_assert_eq(ret, 0, "Failed to initiliaze VFIO sub-system"); + + /* Parse FPGA configuration */ + ret = fpga_parse_cards(cfg_root); + cr_assert_eq(ret, 0, "Failed to parse FPGA config"); + + card = fpga_lookup_card("vc707"); + cr_assert(card, "FPGA card not found"); + + if (criterion_options.logging_threshold < CRITERION_IMPORTANT) + fpga_card_dump(card); +} + +static void fini() +{ + int ret; + + ret = fpga_card_destroy(card); + cr_assert_eq(ret, 0, "Failed to de-initilize FPGA"); + + super_node_destroy(&sn); +} + +TestSuite(fpga, + .init = init, + .fini = fini, + .description = "VILLASfpga"); + +Test(fpga, intc, .description = "Interrupt Controller") +{ + int ret; + uint32_t isr; + + cr_assert(card->intc); + + ret = intc_enable(card->intc, 0xFF00, 0); + cr_assert_eq(ret, 0, "Failed to enable interrupt"); + + /* Fake IRQs in software by writing to ISR */ + XIntc_Out32((uintptr_t) card->map + card->intc->baseaddr + XIN_ISR_OFFSET, 0xFF00); + + /* Wait for 8 SW triggered IRQs */ + for (int i = 0; i < 8; i++) + intc_wait(card->intc, i+8); + + /* Check ISR if all SW IRQs have been deliverd */ + isr = XIntc_In32((uintptr_t) card->map + card->intc->baseaddr + XIN_ISR_OFFSET); + + ret = intc_disable(card->intc, 0xFF00); + cr_assert_eq(ret, 0, "Failed to disable interrupt"); + + cr_assert_eq(isr & 0xFF00, 0); /* ISR should get cleared by MSI_Grant_signal */ +} + +Test(fpga, xsg, .description = "XSG: multiply_add") +{ + int ret; + double factor, err = 0; + + struct fpga_ip *ip, *dma; + struct model_param *p; + struct dma_mem mem; + + ip = fpga_vlnv_lookup(&card->ips, &(struct fpga_vlnv) { NULL, "sysgen", "xsg_multiply", NULL }); + cr_assert(ip); + + dma = fpga_vlnv_lookup(&card->ips, &(struct fpga_vlnv) { "xilinx.com", "ip", "axi_dma", NULL }); + cr_assert(dma); + + struct model *model = (struct model *) ip->_vd; + + p = list_lookup(&model->parameters, "factor"); + if (!p) + error("Missing parameter 'factor' for model '%s'", ip->name); + + ret = model_param_read(p, &factor); + cr_assert_eq(ret, 0, "Failed to read parameter 'factor' from model '%s'", ip->name); + + info("Model param: factor = %f", factor); + + ret = switch_connect(card->sw, dma, ip); + cr_assert_eq(ret, 0, "Failed to configure switch"); + + ret = switch_connect(card->sw, ip, dma); + cr_assert_eq(ret, 0, "Failed to configure switch"); + + ret = dma_alloc(dma, &mem, 0x1000, 0); + cr_assert_eq(ret, 0, "Failed to allocate DMA memory"); + + float *src = (float *) mem.base_virt; + float *dst = (float *) mem.base_virt + 0x800; + + for (int i = 0; i < 6; i++) + src[i] = 1.1 * (i+1); + + ret = dma_ping_pong(dma, (char *) src, (char *) dst, 6 * sizeof(float)); + cr_assert_eq(ret, 0, "Failed to to ping pong DMA transfer: %d", ret); + + for (int i = 0; i < 6; i++) + err += abs(factor * src[i] - dst[i]); + + info("Error after FPGA operation: err = %f", err); + + ret = switch_disconnect(card->sw, dma, ip); + cr_assert_eq(ret, 0, "Failed to configure switch"); + + ret = switch_disconnect(card->sw, ip, dma); + cr_assert_eq(ret, 0, "Failed to configure switch"); + + ret = dma_free(dma, &mem); + cr_assert_eq(ret, 0, "Failed to release DMA memory"); + + cr_assert(err < 1e-3); +} + +Test(fpga, hls_dft, .description = "HLS: hls_dft") +{ + int ret; + struct fpga_ip *hls, *rtds; + + rtds = fpga_vlnv_lookup(&card->ips, &(struct fpga_vlnv) { "acs.eonerc.rwth-aachen.de", "user", "rtds_axis", NULL }); + hls = fpga_vlnv_lookup(&card->ips, &(struct fpga_vlnv) { NULL, "hls", "hls_dft", NULL }); + + /* Check if required IP is available on FPGA */ + cr_assert(hls && rtds); + + ret = intc_enable(card->intc, (1 << rtds->irq), 0); + cr_assert_eq(ret, 0, "Failed to enable interrupt"); + + ret = switch_connect(card->sw, rtds, hls); + cr_assert_eq(ret, 0, "Failed to configure switch"); + + ret = switch_connect(card->sw, hls, rtds); + cr_assert_eq(ret, 0, "Failed to configure switch"); + + while(1) { + /* Dump RTDS AXI Stream state */ + rtds_axis_dump(rtds); + sleep(1); + } +#if 0 + int len = 2000; + int NSAMPLES = 400; + float src[len], dst[len]; + + for (int i = 0; i < len; i++) { + src[i] = 4 + 5.0 * sin(2.0 * M_PI * 1 * i / NSAMPLES) + + 2.0 * sin(2.0 * M_PI * 2 * i / NSAMPLES) + + 1.0 * sin(2.0 * M_PI * 5 * i / NSAMPLES) + + 0.5 * sin(2.0 * M_PI * 9 * i / NSAMPLES) + + 0.2 * sin(2.0 * M_PI * 15 * i / NSAMPLES); + + fifo_write() + } +#endif + + ret = switch_disconnect(card->sw, rtds, hls); + cr_assert_eq(ret, 0, "Failed to configure switch"); + + ret = switch_disconnect(card->sw, hls, rtds); + cr_assert_eq(ret, 0, "Failed to configure switch"); +} + +Test(fpga, fifo, .description = "FIFO") +{ + int ret; + ssize_t len; + char src[255], dst[255]; + struct fpga_ip *fifo; + + fifo = fpga_vlnv_lookup(&card->ips, &(struct fpga_vlnv) { "xilinx.com", "ip", "axi_fifo_mm_s", NULL }); + cr_assert(fifo); + + ret = intc_enable(card->intc, (1 << fifo->irq), 0); + cr_assert_eq(ret, 0, "Failed to enable interrupt"); + + ret = switch_connect(card->sw, fifo, fifo); + cr_assert_eq(ret, 0, "Failed to configure switch"); + + /* Get some random data to compare */ + memset(dst, 0, sizeof(dst)); + len = read_random((char *) src, sizeof(src)); + if (len != sizeof(src)) + error("Failed to get random data"); + + len = fifo_write(fifo, (char *) src, sizeof(src)); + if (len != sizeof(src)) + error("Failed to send to FIFO"); + + len = fifo_read(fifo, (char *) dst, sizeof(dst)); + if (len != sizeof(dst)) + error("Failed to read from FIFO"); + + ret = intc_disable(card->intc, (1 << fifo->irq)); + cr_assert_eq(ret, 0, "Failed to disable interrupt"); + + ret = switch_disconnect(card->sw, fifo, fifo); + cr_assert_eq(ret, 0, "Failed to configure switch"); + + /* Compare data */ + cr_assert_eq(memcmp(src, dst, sizeof(src)), 0); +} + +Test(fpga, dma, .description = "DMA") +{ + int ret = -1; + struct dma_mem mem, src, dst; + + for (size_t i = 0; i < list_length(&card->ips); i++) { INDENT + struct fpga_ip *dm = list_at(&card->ips, i); + + if (fpga_vlnv_cmp(&dm->vlnv, &(struct fpga_vlnv) { "xilinx.com", "ip", "axi_dma", NULL })) + continue; /* skip non DMA IP cores */ + + struct dma *dma = (struct dma *) dm->_vd; + + /* Simple DMA can only transfer up to 4 kb due to + * PCIe page size burst limitation */ + ssize_t len2, len = dma->inst.HasSg ? 64 << 20 : 1 << 2; + + ret = dma_alloc(dm, &mem, 2 * len, 0); + cr_assert_eq(ret, 0); + + ret = dma_mem_split(&mem, &src, &dst); + cr_assert_eq(ret, 0); + + /* Get new random data */ + len2 = read_random(src.base_virt, len); + if (len2 != len) + serror("Failed to get random data"); + + int irq_mm2s = dm->irq; + int irq_s2mm = dm->irq + 1; + + ret = intc_enable(card->intc, (1 << irq_mm2s) | (1 << irq_s2mm), 0); + cr_assert_eq(ret, 0, "Failed to enable interrupt"); + + ret = switch_connect(card->sw, dm, dm); + cr_assert_eq(ret, 0, "Failed to configure switch"); + + /* Start transfer */ + ret = dma_ping_pong(dm, src.base_phys, dst.base_phys, dst.len); + cr_assert_eq(ret, 0, "DMA ping pong failed"); + + ret = memcmp(src.base_virt, dst.base_virt, src.len); + + info("DMA %s (%s): %s", dm->name, dma->inst.HasSg ? "scatter-gather" : "simple", ret ? RED("failed") : GRN("passed")); + + ret = switch_disconnect(card->sw, dm, dm); + cr_assert_eq(ret, 0, "Failed to configure switch"); + + ret = intc_disable(card->intc, (1 << irq_mm2s) | (1 << irq_s2mm)); + cr_assert_eq(ret, 0, "Failed to disable interrupt"); + + ret = dma_free(dm, &mem); + cr_assert_eq(ret, 0, "Failed to release DMA memory"); + } + + cr_assert_eq(ret, 0); +} + +Test(fpga, timer, .description = "Timer Counter") +{ + int ret; + struct fpga_ip *ip; + struct timer *tmr; + + ip = fpga_vlnv_lookup(&card->ips, &(struct fpga_vlnv) { "xilinx.com", "ip", "axi_timer", NULL }); + cr_assert(ip); + + tmr = (struct timer *) ip->_vd; + + XTmrCtr *xtmr = &tmr->inst; + + ret = intc_enable(card->intc, (1 << ip->irq), 0); + cr_assert_eq(ret, 0, "Failed to enable interrupt"); + + XTmrCtr_SetOptions(xtmr, 0, XTC_EXT_COMPARE_OPTION | XTC_DOWN_COUNT_OPTION); + XTmrCtr_SetResetValue(xtmr, 0, FPGA_AXI_HZ / 125); + XTmrCtr_Start(xtmr, 0); + + uint64_t counter = intc_wait(card->intc, ip->irq); + info("Got IRQ: counter = %ju", counter); + + if (counter == 1) + return; + else + warn("Counter was not 1"); + + intc_disable(card->intc, (1 << ip->irq)); + cr_assert_eq(ret, 0, "Failed to disable interrupt"); + + return; +} + +Test(fpga, rtds_rtt, .description = "RTDS: tight rtt") +{ + int ret; + struct fpga_ip *ip, *rtds; + struct dma_mem buf; + size_t recvlen; + + /* Get IP cores */ + rtds = fpga_vlnv_lookup(&card->ips, &(struct fpga_vlnv) { "acs.eonerc.rwth-aachen.de", "user", "rtds_axis", NULL }); + cr_assert(rtds); + + ip = fpga_vlnv_lookup(&card->ips, &(struct fpga_vlnv) { "xilinx.com", "ip", "axi_dma", NULL }); + cr_assert(ip); + + ret = switch_connect(card->sw, rtds, ip); + cr_assert_eq(ret, 0, "Failed to configure switch"); + + ret = switch_connect(card->sw, ip, rtds); + cr_assert_eq(ret, 0, "Failed to configure switch"); + + ret = dma_alloc(ip, &buf, 0x100, 0); + cr_assert_eq(ret, 0, "Failed to allocate DMA memory"); + + while (1) { + + ret = dma_read(ip, buf.base_phys, buf.len); + cr_assert_eq(ret, 0, "Failed to start DMA read: %d", ret); + + ret = dma_read_complete(ip, NULL, &recvlen); + cr_assert_eq(ret, 0, "Failed to complete DMA read: %d", ret); + + ret = dma_write(ip, buf.base_phys, recvlen); + cr_assert_eq(ret, 0, "Failed to start DMA write: %d", ret); + + ret = dma_write_complete(ip, NULL, NULL); + cr_assert_eq(ret, 0, "Failed to complete DMA write: %d", ret); + } + + ret = switch_disconnect(card->sw, rtds, ip); + cr_assert_eq(ret, 0, "Failed to configure switch"); + + ret = switch_disconnect(card->sw, ip, rtds); + cr_assert_eq(ret, 0, "Failed to configure switch"); + + ret = dma_free(ip, &buf); + cr_assert_eq(ret, 0, "Failed to release DMA memory"); +} \ No newline at end of file diff --git a/tests/hist.c b/tests/unit/hist.c similarity index 85% rename from tests/hist.c rename to tests/unit/hist.c index 79dab8655..58221c7df 100644 --- a/tests/hist.c +++ b/tests/unit/hist.c @@ -1,7 +1,7 @@ /** Unit tests for histogram * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include @@ -16,8 +16,10 @@ const int hist_result[] = {}; Test(hist, simple) { struct hist h; + int ret; - hist_create(&h, -100, 100, 1); + ret = hist_init(&h, -100, 100, 1); + cr_assert_eq(ret, 0); for (int i = 0; i < ARRAY_LEN(test_data); i++) hist_put(&h, test_data[i]); diff --git a/tests/list.c b/tests/unit/list.c similarity index 68% rename from tests/list.c rename to tests/unit/list.c index 7270d6e1c..0b6cfa0de 100644 --- a/tests/list.c +++ b/tests/unit/list.c @@ -1,7 +1,7 @@ /** Unit tests for array-based list * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include @@ -20,7 +20,7 @@ struct data { Test(list, list_lookup) { - struct list l; + struct list l = { .state = STATE_DESTROYED }; list_init(&l); @@ -42,26 +42,26 @@ Test(list, list_lookup) Test(list, list_search) { - struct list l; + struct list l = { .state = STATE_DESTROYED }; list_init(&l); /* Fill list */ for (int i = 0; i < ARRAY_LEN(nouns); i++) list_push(&l, nouns[i]); + + cr_assert_eq(list_length(&l), ARRAY_LEN(nouns)); /* Declare on stack! */ char positive[] = "woman"; char negative[] = "dinosaurrier"; - char *found = (char *) list_search(&l, (cmp_cb_t) strcmp, positive); - + char *found = list_search(&l, (cmp_cb_t) strcmp, positive); cr_assert_not_null(found); - cr_assert_eq(found, nouns[13]); + cr_assert_eq(found, nouns[13], "found = %p, nouns[13] = %p", found, nouns[13]); cr_assert_str_eq(found, positive); char *not_found = (char *) list_search(&l, (cmp_cb_t) strcmp, negative); - cr_assert_null(not_found); list_destroy(&l, NULL, false); @@ -71,16 +71,18 @@ struct content { int destroyed; }; -static void dtor(void *ptr) +static int dtor(void *ptr) { struct content *elm = (struct content *) ptr; elm->destroyed = 1; + + return 0; } Test(list, destructor) { - struct list l; + struct list l = { .state = STATE_DESTROYED }; struct content elm = { .destroyed = 0 }; list_init(&l); @@ -100,7 +102,8 @@ static int compare(const void *a, const void *b) { Test(list, basics) { intptr_t i; - struct list l; + int ret; + struct list l = { .state = STATE_DESTROYED }; list_init(&l); @@ -114,25 +117,31 @@ Test(list, basics) cr_assert_eq(list_last(&l), (void *) 99); cr_assert_eq(list_first(&l), NULL); - i = 0; - list_foreach (void *j, &l) - cr_assert_eq(j, (void *) i++); + for (size_t j = 0, i = 0; j < list_length(&l); j++) { + void *k = list_at(&l, j); + + cr_assert_eq(k, (void *) i++); + } list_sort(&l, compare); /* Reverse list */ - i = 99; - list_foreach (void *j, &l) { - cr_assert_eq(j, (void *) i, "Is %p, expected %p", i, j); + for (size_t j = 0, i = 99; j < list_length(&l); j++) { + void *k = list_at(&l, j); + + cr_assert_eq(k, (void *) i, "Is %p, expected %p", i, k); i--; } - cr_assert(list_contains(&l, (void *) 55)); + ret = list_contains(&l, (void *) 55); + cr_assert(ret); list_remove(&l, (void *) 55); - cr_assert(!list_contains(&l, (void *) 55)); + ret = list_contains(&l, (void *) 55); + cr_assert(!ret); list_destroy(&l, NULL, false); - cr_assert_eq(list_length(&l), -1, "List not properly destroyed: l.length = %zd", l.length); + ret = list_length(&l); + cr_assert_eq(ret, -1, "List not properly destroyed: l.length = %zd", l.length); } \ No newline at end of file diff --git a/tests/unit/log.c b/tests/unit/log.c new file mode 100644 index 000000000..3718306ac --- /dev/null +++ b/tests/unit/log.c @@ -0,0 +1,51 @@ +/** Unit tests for log functions + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#include +#include + +#include "log.h" +#include "utils.h" + +struct param { + char *expression; + long expected; +}; + +static struct log l; + +static void init() +{ + log_init(&l, V, LOG_ALL); +} + +static void fini() +{ + log_destroy(&l); +} + +ParameterizedTestParameters(log, facility_expression) +{ + static struct param params[] = { + { "all,!pool", LOG_ALL & ~LOG_POOL }, + { "pool,!pool", LOG_POOL & ~LOG_POOL }, + { "pool,nodes,!socket", (LOG_POOL | LOG_NODES) & ~LOG_SOCKET }, + { "kernel", LOG_KERNEL }, + { "ngsi", LOG_NGSI }, + { "all", LOG_ALL }, + { "!all", 0 }, + { "", 0 } + }; + + return cr_make_param_array(struct param, params, ARRAY_LEN(params)); +} + +ParameterizedTest(struct param *p, log, facility_expression, .init = init, .fini = fini) +{ + log_set_facility_expression(&l, p->expression); + + cr_assert_eq(l.facilities, p->expected, "log.faciltities is %#lx not %#lx", l.facilities, p->expected); +} \ No newline at end of file diff --git a/tests/unit/main.c b/tests/unit/main.c new file mode 100644 index 000000000..fcb12e5f1 --- /dev/null +++ b/tests/unit/main.c @@ -0,0 +1,30 @@ +/** Custom main() for Criterion + * + * @author Steffen Vogel + * @copyright 2014-2016, Institute for Automation of Complex Power Systems, EONERC + * This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + *********************************************************************************/ + +#include + +#include +#include + +#include "config.h" + +int main(int argc, char *argv[]) { + + struct criterion_test_set *tests = criterion_initialize(); + struct log log; + + log_init(&log, V, LOG_ALL); + memory_init(DEFAULT_NR_HUGEPAGES); + + int result = 0; + if (criterion_handle_args(argc, argv, true)) + result = !criterion_run_all_tests(tests); + + criterion_finalize(tests); + return result; +} \ No newline at end of file diff --git a/tests/unit/mapping.c b/tests/unit/mapping.c new file mode 100644 index 000000000..44549fa6a --- /dev/null +++ b/tests/unit/mapping.c @@ -0,0 +1,80 @@ +/** Unit tests for sample value mapping. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#include + +#include "mapping.h" + +Test(mapping, parse) +{ + int ret; + struct mapping_entry m; + + ret = mapping_entry_parse_str(&m, "ts.origin"); + cr_assert_eq(ret, 0); + cr_assert_eq(m.type, MAPPING_TYPE_TIMESTAMP); + cr_assert_eq(m.timestamp.id, MAPPING_TIMESTAMP_ORIGIN); + + ret = mapping_entry_parse_str(&m, "hdr.sequence"); + cr_assert_eq(ret, 0); + cr_assert_eq(m.type, MAPPING_TYPE_HEADER); + cr_assert_eq(m.header.id, MAPPING_HEADER_SEQUENCE); + + ret = mapping_entry_parse_str(&m, "stats.owd.mean"); + cr_assert_eq(ret, 0); + cr_assert_eq(m.type, MAPPING_TYPE_STATS); + cr_assert_eq(m.stats.id, STATS_OWD); + cr_assert_eq(m.stats.type, MAPPING_STATS_TYPE_MEAN); + + ret = mapping_entry_parse_str(&m, "data[1-2]"); + cr_assert_eq(ret, 0); + cr_assert_eq(m.type, MAPPING_TYPE_DATA); + cr_assert_eq(m.data.offset, 1); + cr_assert_eq(m.length, 2); + + ret = mapping_entry_parse_str(&m, "data[5-5]"); + cr_assert_eq(ret, 0); + cr_assert_eq(m.type, MAPPING_TYPE_DATA); + cr_assert_eq(m.data.offset, 5); + cr_assert_eq(m.length, 1); + + ret = mapping_entry_parse_str(&m, "data[22]"); + cr_assert_eq(ret, 0); + cr_assert_eq(m.type, MAPPING_TYPE_DATA); + cr_assert_eq(m.data.offset, 22); + cr_assert_eq(m.length, 1); + + ret = mapping_entry_parse_str(&m, "data[]"); + cr_assert_neq(ret, 0); + + ret = mapping_entry_parse_str(&m, "data[1.1-2f]"); + cr_assert_neq(ret, 0); + + /* Missing parts */ + ret = mapping_entry_parse_str(&m, "stats.owd"); + cr_assert_neq(ret, 0); + + ret = mapping_entry_parse_str(&m, "data"); + cr_assert_neq(ret, 0); + + /* This a type */ + ret = mapping_entry_parse_str(&m, "hdr.sequences"); + cr_assert_neq(ret, 0); + + /* Check for superfluous chars at the end */ + ret = mapping_entry_parse_str(&m, "stats.ts.origin.bla"); + cr_assert_neq(ret, 0); + + ret = mapping_entry_parse_str(&m, "stats.ts.origin."); + cr_assert_neq(ret, 0); + + ret = mapping_entry_parse_str(&m, "data[1-2]bla"); + cr_assert_neq(ret, 0); + + /* Negative length of chunk */ + ret = mapping_entry_parse_str(&m, "data[5-3]"); + cr_assert_eq(ret, -1); +} \ No newline at end of file diff --git a/tests/memory.c b/tests/unit/memory.c similarity index 83% rename from tests/memory.c rename to tests/unit/memory.c index 69234930d..e7821e02e 100644 --- a/tests/memory.c +++ b/tests/unit/memory.c @@ -1,7 +1,7 @@ /** Unit tests for memory management * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include @@ -13,8 +13,7 @@ #include "utils.h" TheoryDataPoints(memory, aligned) = { -// DataPoints(size_t, 1, 32, 55, 1 << 10, 1 << 20), - DataPoints(size_t, 1<<12), + DataPoints(size_t, 1, 32, 55, 1 << 10, 1 << 20), DataPoints(size_t, 1, 8, 1 << 12), DataPoints(const struct memtype *, &memtype_heap, &memtype_hugepage) }; @@ -26,7 +25,7 @@ Theory((size_t len, size_t align, const struct memtype *m), memory, aligned) { ptr = memory_alloc_aligned(m, len, align); cr_assert_neq(ptr, NULL, "Failed to allocate memory"); - //cr_assert(IS_ALIGNED(ptr, align)); + cr_assert(IS_ALIGNED(ptr, align)); if (m == &memtype_hugepage) { cr_assert(IS_ALIGNED(ptr, HUGEPAGESIZE)); diff --git a/tests/pool.c b/tests/unit/pool.c similarity index 92% rename from tests/pool.c rename to tests/unit/pool.c index e871e6041..a036bcbe1 100644 --- a/tests/pool.c +++ b/tests/unit/pool.c @@ -1,7 +1,7 @@ /** Unit tests for memory pool * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include @@ -34,7 +34,7 @@ ParameterizedTestParameters(pool, basic) ParameterizedTest(struct param *p, pool, basic) { int ret; - struct pool pool; + struct pool pool = { .state = STATE_DESTROYED }; void *ptr, *ptrs[p->pool_size]; diff --git a/tests/queue.c b/tests/unit/queue.c similarity index 91% rename from tests/queue.c rename to tests/unit/queue.c index 35bc79b11..e75caa408 100644 --- a/tests/queue.c +++ b/tests/unit/queue.c @@ -1,3 +1,9 @@ +/** Unit tests for queue + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + #include #include #include @@ -15,7 +21,7 @@ #define SIZE (1 << 10) -static struct queue q; +static struct queue q = { .state = STATE_DESTROYED }; struct param { int volatile start; @@ -55,7 +61,7 @@ __attribute__((always_inline)) static inline void nop() static void * producer(void *ctx) { int ret; - struct param *p = (struct param *) ctx; + struct param *p = ctx; srand((unsigned) time(0) + thread_get_id()); size_t nops = rand() % 1000; @@ -91,7 +97,7 @@ static void * producer(void *ctx) static void * consumer(void *ctx) { int ret; - struct param *p = (struct param *) ctx; + struct param *p = ctx; srand((unsigned) time(0) + thread_get_id()); size_t nops = rand() % 1000; @@ -130,7 +136,7 @@ static void * consumer(void *ctx) void * producer_consumer(void *ctx) { - struct param *p = (struct param *) ctx; + struct param *p = ctx; srand((unsigned) time(0) + thread_get_id()); size_t nops = rand() % 1000; @@ -162,7 +168,7 @@ void * producer_consumer(void *ctx) void * producer_consumer_many(void *ctx) { - struct param *p = (struct param *) ctx; + struct param *p = ctx; srand((unsigned) time(0) + thread_get_id()); size_t nops = rand() % 1000; @@ -278,7 +284,7 @@ ParameterizedTest(struct param *p, queue, multi_threaded, .timeout = 10) uint64_t start_tsc_time, end_tsc_time; for (int i = 0; i < p->thread_count; ++i) - pthread_create(&threads[i], NULL, p->thread_func, &p); + pthread_create(&threads[i], NULL, p->thread_func, p); sleep(1); @@ -294,18 +300,19 @@ ParameterizedTest(struct param *p, queue, multi_threaded, .timeout = 10) if (cycpop < 400) cr_log_info("cycles/op: %u\n", cycpop); else - cr_log_warn("cycles/op are very high (%u). Are you running on a a hypervisor?\n", cycpop); + cr_log_warn("cycles/op are very high (%u). Are you running on a hypervisor?\n", cycpop); - cr_assert_eq(queue_available(&q), 0); + ret = queue_available(&q); + cr_assert_eq(ret, 0); ret = queue_destroy(&p->queue); - cr_assert_eq(ret, 0, "Failed to create queue"); + cr_assert_eq(ret, 0, "Failed to destroy queue"); } Test(queue, init_destroy) { int ret; - struct queue q; + struct queue q = { .state = STATE_DESTROYED }; ret = queue_init(&q, 1024, &memtype_heap); cr_assert_eq(ret, 0); /* Should succeed */ diff --git a/tests/unit/sample_io.c b/tests/unit/sample_io.c new file mode 100644 index 000000000..9daffb536 --- /dev/null +++ b/tests/unit/sample_io.c @@ -0,0 +1,79 @@ +/** Unit tests for the sample_io module. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#include + +#include +#include + +#include "utils.h" +#include "timing.h" +#include "sample.h" +#include "sample_io.h" + +ParameterizedTestParameters(sample_io, read_write) +{ + static enum sample_io_format formats[] = { + SAMPLE_IO_FORMAT_VILLAS, + SAMPLE_IO_FORMAT_JSON, + }; + + return cr_make_param_array(enum sample_io_format, formats, ARRAY_LEN(formats)); +} + +ParameterizedTest(enum sample_io_format *fmt, sample_io, read_write) +{ + FILE *f; + int ret; + struct sample *s, *t; + + /* Prepare a sample with arbitrary data */ + s = malloc(SAMPLE_LEN(16)); + cr_assert_not_null(s); + + t = malloc(SAMPLE_LEN(16)); + cr_assert_not_null(s); + + t->capacity = + s->capacity = 16; + s->length = 12; + s->sequence = 235; + s->format = 0; + s->ts.origin = time_now(); + s->ts.received = (struct timespec) { s->ts.origin.tv_sec - 1, s->ts.origin.tv_nsec }; + + for (int i = 0; i < s->length; i++) + s->data[i].f = i * 1.2; + + /* Open a file for IO */ + f = tmpfile(); + cr_assert_not_null(f); + + ret = sample_io_fprint(f, s, *fmt, SAMPLE_IO_ALL); + cr_assert_eq(ret, 0); + + rewind(f); + + ret = sample_io_fscan(f, t, *fmt, NULL); + cr_assert_eq(ret, 0); + + cr_assert_eq(s->length, t->length); + cr_assert_eq(s->sequence, t->sequence); + cr_assert_eq(s->format, t->format); + + cr_assert_eq(s->ts.origin.tv_sec, t->ts.origin.tv_sec); + cr_assert_eq(s->ts.origin.tv_nsec, t->ts.origin.tv_nsec); + cr_assert_eq(s->ts.received.tv_sec, t->ts.received.tv_sec); + cr_assert_eq(s->ts.received.tv_nsec, t->ts.received.tv_nsec); + + for (int i = 0; i < MIN(s->length, t->length); i++) + cr_assert_float_eq(s->data[i].f, t->data[i].f, 1e-6); + + fclose(f); + + free(s); + free(t); +} \ No newline at end of file diff --git a/tests/timing.c b/tests/unit/timing.c similarity index 97% rename from tests/timing.c rename to tests/unit/timing.c index 4a3ca3d91..2e9f27522 100644 --- a/tests/timing.c +++ b/tests/unit/timing.c @@ -1,7 +1,7 @@ /** Unit tests for time related utlities * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include diff --git a/tests/utils.c b/tests/unit/utils.c similarity index 65% rename from tests/utils.c rename to tests/unit/utils.c index fe649319b..688d3ff70 100644 --- a/tests/utils.c +++ b/tests/unit/utils.c @@ -1,7 +1,7 @@ /** Unit tests for utilities * * @author Steffen Vogel - * @copyright 2016, Institute for Automation of Complex Power Systems, EONERC + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ #include @@ -59,4 +59,27 @@ Test(utils, version) cr_assert_eq(version_cmp(&v1, &v1), 0); cr_assert_gt(version_cmp(&v2, &v1), 0); cr_assert_lt(version_cmp(&v3, &v4), 0); +} + +Test(utils, sha1sum) +{ + int ret; + FILE *f = tmpfile(); + + unsigned char hash[SHA_DIGEST_LENGTH]; + unsigned char expected[SHA_DIGEST_LENGTH] = { 0x69, 0xdf, 0x29, 0xdf, 0x1f, 0xf2, 0xd2, 0x5d, 0xb8, 0x68, 0x6c, 0x02, 0x8d, 0xdf, 0x40, 0xaf, 0xb3, 0xc1, 0xc9, 0x4d }; + + /* Write the first 512 fibonaccia numbers to the file */ + for (int i = 0, a = 0, b = 1, c; i < 512; i++, a = b, b = c) { + c = a + b; + + fwrite((void *) &c, sizeof(c), 1, f); + } + + ret = sha1sum(f, hash); + + cr_assert_eq(ret, 0); + cr_assert_arr_eq(hash, expected, SHA_DIGEST_LENGTH); + + fclose(f); } \ No newline at end of file diff --git a/thirdparty/Makefile.inc b/thirdparty/Makefile.inc index 7fc108858..4d09d980a 100644 --- a/thirdparty/Makefile.inc +++ b/thirdparty/Makefile.inc @@ -14,7 +14,7 @@ $(DEPS_AUTOCONF): | $(BUILDDIR)/thirdparty/$$@/ $(DEPS_CMAKE): | $(BUILDDIR)/thirdparty/$$@/ cmake -DCMAKE_INSTALL_PREFIX:PATH=$(PREFIX) \ -H$(SRCDIR)/thirdparty/$@ \ - -B$(BUILDDIR)/thirdparty/$@ + -B$(BUILDDIR)/thirdparty/$@ $(CMAKE_OPTS) make -C$(BUILDDIR)/thirdparty/$@ $(addprefix install-,$(DEPS)): install-%: % @@ -24,16 +24,17 @@ $(addprefix install-,$(DEPS)): install-%: % $(addprefix clean-,$(DEPS)): rm -rf $(BUILDDIR)/thirdparty/$(@:clean-%=%) -install-thirdparty: +install-thirdparty: $(addprefix install-,$(DEPS)) -clean-thirdparty: +clean-thirdparty: $(addprefix clean-,$(DEPS)) rm -rf $(BUILDDIR)/thirdparty -.PHONY: $(DEPS) thirdparty clean-thirdparty install-thirdparty - - # libconfig's build system is currently broken. # This is a workaround for: https://github.com/hyperrealm/libconfig/issues/53 libconfig: | libconfig-fix libconfig-fix: - rm -f $(SRCDIR)/thirdparty/libconfig/lib/scanner.[hc] \ No newline at end of file + rm -f $(SRCDIR)/thirdparty/libconfig/lib/scanner.[hc] + +libwebsockets: CMAKE_OPTS = -DLWS_IPV6=1 -DLWS_WITH_STATIC=0 -DLWS_WITHOUT_TESTAPPS=1 -DLWS_WITH_HTTP2=1 + +.PHONY: $(DEPS) thirdparty clean-thirdparty install-thirdparty \ No newline at end of file diff --git a/thirdparty/criterion b/thirdparty/criterion index 101d0e0f3..3b90b8d18 160000 --- a/thirdparty/criterion +++ b/thirdparty/criterion @@ -1 +1 @@ -Subproject commit 101d0e0f3a71c414c7d2a7a2a2fa465969b6b667 +Subproject commit 3b90b8d188be9d224907d576a5c69e8e8d4190cf diff --git a/thirdparty/libnl b/thirdparty/libnl index 7bf2e6465..54344bc06 160000 --- a/thirdparty/libnl +++ b/thirdparty/libnl @@ -1 +1 @@ -Subproject commit 7bf2e64654de75578db34b0eab53a3e4d106d65f +Subproject commit 54344bc0631b16eb623bfbd91e6f7b3d03b27c09 diff --git a/thirdparty/libwebsockets b/thirdparty/libwebsockets index 0c984014f..07fa6252c 160000 --- a/thirdparty/libwebsockets +++ b/thirdparty/libwebsockets @@ -1 +1 @@ -Subproject commit 0c984014f0a82e184af2ff18f97b45e2cbccd0bd +Subproject commit 07fa6252cf4a76e8ce1951ba74a4f110276f9180 diff --git a/thirdparty/libxil b/thirdparty/libxil new file mode 160000 index 000000000..4df97a4cd --- /dev/null +++ b/thirdparty/libxil @@ -0,0 +1 @@ +Subproject commit 4df97a4cd8fc661f87d95e15d2a954376308e5f3 diff --git a/thirdparty/libxil/.gitignore b/thirdparty/libxil/.gitignore deleted file mode 100644 index c038681dc..000000000 --- a/thirdparty/libxil/.gitignore +++ /dev/null @@ -1 +0,0 @@ -libxil.so \ No newline at end of file diff --git a/thirdparty/libxil/CMakeLists.txt b/thirdparty/libxil/CMakeLists.txt deleted file mode 100644 index f710497e5..000000000 --- a/thirdparty/libxil/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required (VERSION 3.2) - -project(libxil C) - -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -fPIC -I$(SRCDIR)/include/xilinx -Iorig/common_v1_00_a/src -Wno-int-conversion -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast") - -file(GLOB SOURCES src/*.c orig/*/src/*.c) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/xilinx) - -add_library(xil SHARED ${SOURCES}) - -include(FindPkgConfig QUIET) -if(PKG_CONFIG_FOUND) - # convert lists of link libraries into -lstdc++ -lm etc.. - foreach(LIB ${CMAKE_CXX_IMPLICIT_LINK_LIBRARIES} ${PLATFORM_LIBS}) - set(PRIVATE_LIBS "${PRIVATE_LIBS} -l${LIB}") - endforeach() - - # Produce a pkg-config file for linking against the shared lib - configure_file("libxil.pc.in" "libxil.pc" @ONLY) - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libxil.pc" DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig") -endif() - -install(TARGETS xil DESTINATION lib) - -file(GLOB HEADERS include/xilinx/*.h) - -# Make sure we dont install symlinks -set (HEADERS_RESOLVED "") -foreach (HEADER ${HEADERS}) - get_filename_component(HEADER_RESOLVED "${HEADER}" REALPATH) - list (APPEND HEADERS_RESOLVED "${HEADER_RESOLVED}") -endforeach() - -install(FILES ${HEADERS_RESOLVED} DESTINATION include/xilinx) \ No newline at end of file diff --git a/thirdparty/libxil/README.md b/thirdparty/libxil/README.md deleted file mode 100644 index c42363e74..000000000 --- a/thirdparty/libxil/README.md +++ /dev/null @@ -1 +0,0 @@ -These drivers are taken from https://github.com/Xilinx/embeddedsw/tree/master/XilinxProcessorIPLib/drivers \ No newline at end of file diff --git a/thirdparty/libxil/include/xilinx/xaxidma.h b/thirdparty/libxil/include/xilinx/xaxidma.h deleted file mode 100644 index 86f62dd65..000000000 --- a/thirdparty/libxil/include/xilinx/xaxidma.h +++ /dev/null @@ -1,741 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xaxidma.h -* @addtogroup axidma_v9_0 -* @{ -* @details -* -* This is the driver API for the AXI DMA engine. -* -* For a full description of DMA features, please see the hardware spec. This -* driver supports the following features: -* -* - Scatter-Gather DMA (SGDMA) -* - Simple DMA -* - Interrupts -* - Programmable interrupt coalescing for SGDMA -* - APIs to manage Buffer Descriptors (BD) movement to and from the SGDMA -* engine -* -* Simple DMA -* -* Simple DMA allows the application to define a single transaction between DMA -* and Device. It has two channels: one from the DMA to Device and the other -* from Device to DMA. Application has to set the buffer address and -* length fields to initiate the transfer in respective channel. -* -* Transactions -* -* The object used to describe a transaction is referred to as a Buffer -* Descriptor (BD). Buffer descriptors are allocated in the user application. -* The user application needs to set buffer address, transfer length, and -* control information for this transfer. The control information includes -* SOF and EOF. Definition of those masks are in xaxidma_hw.h -* -* Scatter-Gather DMA -* -* SGDMA allows the application to define a list of transactions in memory which -* the hardware will process without further application intervention. During -* this time, the application is free to continue adding more work to keep the -* Hardware busy. -* -* User can check for the completion of transactions through polling the -* hardware, or interrupts. -* -* SGDMA processes whole packets. A packet is defined as a series of -* data bytes that represent a message. SGDMA allows a packet of data to be -* broken up into one or more transactions. For example, take an Ethernet IP -* packet which consists of a 14 byte header followed by a 1 or more bytes of -* payload. With SGDMA, the application may point a BD to the header and another -* BD to the payload, then transfer them as a single message. This strategy can -* make a TCP/IP stack more efficient by allowing it to keep packet header and -* data in different memory regions instead of assembling packets into -* contiguous blocks of memory. -* -* BD Ring Management -* -* BD rings are shared by the software and the hardware. -* -* The hardware expects BDs to be setup as a linked list. The DMA hardware walks -* through the list by following the next pointer field of a completed BD. -* The hardware stops processing when the just completed BD is the same as the -* BD specified in the Tail Ptr register in the hardware. -* -* The last BD in the ring is linked to the first BD in the ring. -* -* All BD management are done inside the driver. The user application should not -* directly modify the BD fields. Modifications to the BD fields should always -* go through the specific API functions. -* -* Within the ring, the driver maintains four groups of BDs. Each group consists -* of 0 or more adjacent BDs: -* -* - Free: The BDs that can be allocated by the application with -* XAxiDma_BdRingAlloc(). -* -* - Pre-process: The BDs that have been allocated with -* XAxiDma_BdRingAlloc(). These BDs are under application control. The -* application modifies these BDs through driver API to prepare them -* for DMA transactions. -* -* - Hardware: The BDs that have been enqueued to hardware with -* XAxiDma_BdRingToHw(). These BDs are under hardware control and may be in a -* state of awaiting hardware processing, in process, or processed by -* hardware. It is considered an error for the application to change BDs -* while they are in this group. Doing so can cause data corruption and lead -* to system instability. -* -* - Post-process: The BDs that have been processed by hardware and have -* been extracted from the Hardware group with XAxiDma_BdRingFromHw(). -* These BDs are under application control. The application can check the -* transfer status of these BDs. The application use XAxiDma_BdRingFree() -* to put them into the Free group. -* -* BDs are expected to transition in the following way for continuous -* DMA transfers: -*
-*
-*         XAxiDma_BdRingAlloc()                   XAxiDma_BdRingToHw()
-*   Free ------------------------> Pre-process ----------------------> Hardware
-*                                                                      |
-*    /|\                                                               |
-*     |   XAxiDma_BdRingFree()                  XAxiDma_BdRingFromHw() |
-*     +--------------------------- Post-process <----------------------+
-*
-* 
-* -* When a DMA transfer is to be cancelled before enqueuing to hardware, -* application can return the requested BDs to the Free group using -* XAxiDma_BdRingUnAlloc(), as shown below: -*
-*
-*         XAxiDma_BdRingUnAlloc()
-*   Free <----------------------- Pre-process
-*
-* 
-* -* The API provides functions for BD list traversal: -* - XAxiDma_BdRingNext() -* - XAxiDma_BdRingPrev() -* -* These functions should be used with care as they do not understand where -* one group ends and another begins. -* -* SGDMA Descriptor Ring Creation -* -* BD ring is created using XAxiDma_BdRingCreate(). The memory for the BD ring -* is allocated by the application, and it has to be contiguous. Physical -* address is required to setup the BD ring. -* -* The applicaiton can use XAxiDma_BdRingMemCalc() to find out the amount of -* memory needed for a certain number of BDs. XAxiDma_BdRingCntCalc() can be -* used to find out how many BDs can be allocated for certain amount of memory. -* -* A helper function, XAxiDma_BdRingClone(), can speed up the BD ring setup if -* the BDs have same types of controls, for example, SOF and EOF. After -* using the XAxiDma_BdRingClone(), the application only needs to setup the -* buffer address and transfer length. Note that certain BDs in one packet, -* for example, the first BD and the last BD, may need to setup special -* control information. -* -* Descriptor Ring State Machine -* -* There are two states of the BD ring: -* -* - HALTED (H), where hardware is not running -* -* - NOT HALTED (NH), where hardware is running -* -* The following diagram shows the state transition for the DMA engine: -* -*
-*   _____ XAxiDma_StartBdRingHw(), or XAxiDma_BdRingStart(),   ______
-*   |   |               or XAxiDma_Resume()                    |    |
-*   | H |----------------------------------------------------->| NH |
-*   |   |<-----------------------------------------------------|    |
-*   -----   XAxiDma_Pause() or XAxiDma_Reset()                 ------
-* 
-* -* Interrupt Coalescing -* -* SGDMA provides control over the frequency of interrupts through interrupt -* coalescing. The DMA engine provides two ways to tune the interrupt -* coalescing: -* -* - The packet threshold counter. Interrupt will fire once the -* programmable number of packets have been processed by the engine. -* -* - The packet delay timer counter. Interrupt will fire once the -* programmable amount of time has passed after processing the last packet, -* and no new packets to process. Note that the interrupt will only fire if -* at least one packet has been processed. -* -* Interrupt -* -* Interrupts are handled by the user application. Each DMA channel has its own -* interrupt ID. The driver provides APIs to enable/disable interrupt, -* and tune the interrupt frequency regarding to packet processing frequency. -* -* Software Initialization -* -* -* To use the Simple mode DMA engine for transfers, the following setup is -* required: -* -* - DMA Initialization using XAxiDma_CfgInitialize() function. This step -* initializes a driver instance for the given DMA engine and resets the -* engine. -* -* - Enable interrupts if chosen to use interrupt mode. The application is -* responsible for setting up the interrupt system, which includes providing -* and connecting interrupt handlers and call back functions, before -* enabling the interrupts. -* -* - Set the buffer address and length field in respective channels to start -* the DMA transfer -* -* To use the SG mode DMA engine for transfers, the following setup are -* required: -* -* - DMA Initialization using XAxiDma_CfgInitialize() function. This step -* initializes a driver instance for the given DMA engine and resets the -* engine. -* -* - BD Ring creation. A BD ring is needed per DMA channel and can be built by -* calling XAxiDma_BdRingCreate(). -* -* - Enable interrupts if chose to use interrupt mode. The application is -* responsible for setting up the interrupt system, which includes providing -* and connecting interrupt handlers and call back functions, before -* enabling the interrupts. -* -* - Start a DMA transfer: Call XAxiDma_BdRingStart() to start a transfer for -* the first time or after a reset, and XAxiDma_BdRingToHw() if the channel -* is already started. Calling XAxiDma_BdRingToHw() when a DMA channel is not -* running will not put the BDs to the hardware, and the BDs will be processed -* later when the DMA channel is started through XAxiDma_BdRingStart(). -* -* How to start DMA transactions -* -* The user application uses XAxiDma_BdRingToHw() to submit BDs to the hardware -* to start DMA transfers. -* -* For both channels, if the DMA engine is currently stopped (using -* XAxiDma_Pause()), the newly added BDs will be accepted but not processed -* until the DMA engine is started, using XAxiDma_BdRingStart(), or resumed, -* using XAxiDma_Resume(). -* -* Software Post-Processing on completed DMA transactions -* -* If the interrupt system has been set up and the interrupts are enabled, -* a DMA channels notifies the software about the completion of a transfer -* through interrupts. Otherwise, the user application can poll for -* completions of the BDs, using XAxiDma_BdRingFromHw() or -* XAxiDma_BdHwCompleted(). -* -* - Once BDs are finished by a channel, the application first needs to fetch -* them from the channel using XAxiDma_BdRingFromHw(). -* -* - On the TX side, the application now could free the data buffers attached to -* those BDs as the data in the buffers has been transmitted. -* -* - On the RX side, the application now could use the received data in the -* buffers attached to those BDs. -* -* - For both channels, completed BDs need to be put back to the Free group -* using XAxiDma_BdRingFree(), so they can be used for future transactions. -* -* - On the RX side, it is the application's responsibility to have BDs ready -* to receive data at any time. Otherwise, the RX channel refuses to -* accept any data if it has no RX BDs. -* -* Examples -* -* We provide five examples to show how to use the driver API: -* - One for SG interrupt mode (xaxidma_example_sg_intr.c), multiple BD/packets transfer -* - One for SG polling mode (xaxidma_example_sg_poll.c), single BD transfer. -* - One for SG polling mode (xaxidma_poll_multi_pkts.c), multiple BD/packets transfer -* - One for simple polling mode (xaxidma_example_simple_poll.c) -* - One for simple Interrupt mode (xaxidma_example_simple_intr.c) -* -* Address Translation -* -* All buffer addresses and BD addresses for the hardware are physical -* addresses. The user application is responsible to provide physical buffer -* address for the BD upon BD ring creation. The user application accesses BD -* through its virtual addess. The driver maintains the address translation -* between the physical and virtual address for BDs. -* -* Cache Coherency -* -* This driver expects all application buffers attached to BDs to be in cache -* coherent memory. If cache is used in the system, buffers for transmit MUST -* be flushed from the cache before passing the associated BD to this driver. -* Buffers for receive MUST be invalidated before accessing the data. -* -* Alignment -* -* For BDs: -* -* Minimum alignment is defined by the constant XAXIDMA_BD_MINIMUM_ALIGNMENT. -* This is the smallest alignment allowed by both hardware and software for them -* to properly work. -* -* If the descriptor ring is to be placed in cached memory, alignment also MUST -* be at least the processor's cache-line size. Otherwise, system instability -* occurs. For alignment larger than the cache line size, multiple cache line -* size alignment is required. -* -* Aside from the initial creation of the descriptor ring (see -* XAxiDma_BdRingCreate()), there are no other run-time checks for proper -* alignment of BDs. -* -* For application data buffers: -* -* Application data buffers may reside on any alignment if DRE is built into the -* hardware. Otherwise, application data buffer must be word-aligned. The word -* is defined by XPAR_AXIDMA_0_M_AXIS_MM2S_TDATA_WIDTH for transmit and -* XPAR_AXIDMA_0_S_AXIS_S2MM_TDATA_WIDTH for receive. -* -* For scatter gather transfers that have more than one BDs in the chain of BDs, -* Each BD transfer length must be multiple of word too. Otherwise, internal -* error happens in the hardware. -* -* Error Handling -* -* The DMA engine will halt on all error conditions. It requires the software -* to do a reset before it can start process new transfer requests. -* -* Restart After Stopping -* -* After the DMA engine has been stopped (through reset or reset after an error) -* the software keeps track of the current BD pointer when reset happens, and -* processing of BDs can be resumed through XAxiDma_BdRingStart(). -* -* Limitations -* -* This driver does not have any mechanisms for mutual exclusion. It is up to -* the application to provide this protection. -* -* Hardware Defaults & Exclusive Use -* -* After the initialization or reset, the DMA engine is in the following -* default mode: -* - All interrupts are disabled. -* -* - Interrupt coalescing counter is 1. -* -* - The DMA engine is not running (halted). Each DMA channel is started -* separately, using XAxiDma_StartBdRingHw() if no BDs are setup for transfer -* yet, or XAxiDma_BdRingStart() otherwise. -* -* The driver has exclusive use of the registers and BDs. All accesses to the -* registers and BDs should go through the driver interface. -* -* Debug Print -* -* To see the debug print for the driver, please put "-DDEBUG" as the extra -* compiler flags in software platform settings. Also comment out the line in -* xdebug.h: "#undef DEBUG". -* -* Changes From v1.00a -* -* . We have changes return type for XAxiDma_BdSetBufAddr() from void to int -* . We added XAxiDma_LookupConfig() so that user does not need to look for the -* hardware settings anymore. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who  Date     Changes
-* ----- ---- -------- -------------------------------------------------------
-* 1.00a jz   05/18/10 First release
-* 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
-*                     updated tcl file, added xaxidma_porting_guide.h
-* 3.00a jz   11/22/10 Support IP core parameters change
-* 4.00a rkv  02/22/11 Added support for simple DMA mode
-*		      New API added for simple DMA mode are
-*			- XAxiDma_Busy
-*			- XAxiDma_SimpleTransfer
-*		      New Macros added for simple DMA mode are
-* 			- XAxiDma_HasSg
-* 			- XAxiDma_IntrEnable
-* 			- XAxiDma_IntrGetEnabled
-* 			- XAxiDma_IntrDisable
-* 			- XAxiDma_IntrGetIrq
-* 			- XAxiDma_IntrAckIrq
-* 5.00a srt  08/25/11  Added support for memory barrier and modified
-*			Cache Macros to have a common API for Microblaze
-*			and Zynq.
-* 6.00a srt  01/24/12 Added support for Multi-Channel DMA mode.
-*		      - Changed APIs:
-*			* XAxiDma_GetRxRing(InstancePtr, RingIndex)
-*			* XAxiDma_Start(XAxiDma * InstancePtr, int RingIndex)
-*			* XAxiDma_Started(XAxiDma * InstancePtr, int RingIndex)
-*			* XAxiDma_Pause(XAxiDma * InstancePtr, int RingIndex)
-*			* XAxiDma_Resume(XAxiDma * InstancePtr, int RingIndex)
-*			* XAxiDma_SimpleTransfer(XAxiDma *InstancePtr,
-*        					u32 BuffAddr, u32 Length,
-*						int Direction, int RingIndex)
-*			* XAxiDma_StartBdRingHw(XAxiDma_BdRing * RingPtr,
-*					int RingIndex)
-*			* XAxiDma_BdRingStart(XAxiDma_BdRing * RingPtr,
-*						 int RingIndex)
-*			* XAxiDma_BdRingToHw(XAxiDma_BdRing * RingPtr,
-*        			int NumBd, XAxiDma_Bd * BdSetPtr, int RingIndex)
-*			* XAxiDma_BdRingDumpRegs(XAxiDma_BdRing * RingPtr,
-*						 int RingIndex)
-*			* XAxiDma_BdRingSnapShotCurrBd(XAxiDma_BdRing * RingPtr,
-*						 int RingIndex)
-*			* XAxiDma_BdSetLength(XAxiDma_Bd *BdPtr,
-*					u32 LenBytes, u32 LengthMask)
-*       		* XAxiDma_BdGetActualLength(BdPtr, LengthMask)
-*			* XAxiDma_BdGetLength(BdPtr, LengthMask)
-*		       - New APIs
-*			* XAxiDma_SelectKeyHole(XAxiDma *InstancePtr,
-*						int Direction, int Select)
-*			* XAxiDma_UpdateBdRingCDesc(XAxiDma_BdRing * RingPtr,
-*						int RingIndex)
-* 7.00a srt  06/18/12  All the APIs changed in v6_00_a are reverted back for
-*		       backward compatibility.
-*			- New API:
-*			  XAxiDma_GetRxIndexRing(InstancePtr, RingIndex)
-* 7.01a srt  10/26/12  - Fixed issue with driver as it fails with IP version
-*		         < 6.00a as the parameter C_NUM_*_CHANNELS is not
-*			 applicable.
-*		       - Changed the logic of MCDMA BD fields Set APIs, to
-*			 clear the field first and then set it.
-* 7.02a srt  01/23/13  Replaced *_TDATA_WIDTH parameters to *_DATA_WIDTH
-*		       (CR 691867)
-*		       Updated DDR base address for IPI designs (CR 703656).
-* 8.0   adk  19/12/13  Updated as per the New Tcl API's
-*	srt  01/29/14  Added support for Micro DMA Mode and cyclic mode of
-*		       operations.
-*		      - New APIs:
-*			* XAxiDma_SelectCyclicMode(XAxiDma *InstancePtr,
-*						int Direction, int Select)
- *			* XAxiDma_BdSetBufAddrMicroMode(XAxiDma_Bd*, u32)
-* 8.1   adk  20/01/15  Added support for peripheral test. Created the self
-*		       test example to include it on peripheral test's(CR#823144).
-* 8.1   adk  29/01/15  Added the sefltest api (XAxiDma_Selftest) to the driver source files
-* 		      (xaxidma_selftest.c) and called this from the selftest example
-* 9.0 	adk  27/07/15  Added support for 64-bit Addressing.
-* 9.0   adk  19/08/15  Fixed CR#873125 DMA SG Mode example tests are failing on
-*		       HW in 2015.3.
-*
-* 
-* -******************************************************************************/ - -#ifndef XAXIDMA_H_ /* prevent circular inclusions */ -#define XAXIDMA_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/***************************** Include Files *********************************/ -#include "xaxidma_bdring.h" -#ifdef __MICROBLAZE__ -#include "xenv.h" -#else -#include -#include "xil_cache.h" -#endif - -/************************** Constant Definitions *****************************/ - - -/**************************** Type Definitions *******************************/ - -/** - * The XAxiDma driver instance data. An instance must be allocated for each DMA - * engine in use. - */ -typedef struct XAxiDma { - u32 RegBase; /* Virtual base address of DMA engine */ - - int HasMm2S; /* Has transmit channel */ - int HasS2Mm; /* Has receive channel */ - int Initialized; /* Driver has been initialized */ - int HasSg; - - XAxiDma_BdRing TxBdRing; /* BD container management for TX channel */ - XAxiDma_BdRing RxBdRing[16]; /* BD container management for RX channel */ - int TxNumChannels; - int RxNumChannels; - int MicroDmaMode; - int AddrWidth; /**< Address Width */ -} XAxiDma; - -/** - * The configuration structure for AXI DMA engine - * - * This structure passes the hardware building information to the driver - */ -typedef struct { - u32 DeviceId; - u32 BaseAddr; - - int HasStsCntrlStrm; - int HasMm2S; - int HasMm2SDRE; - int Mm2SDataWidth; - int HasS2Mm; - int HasS2MmDRE; - int S2MmDataWidth; - int HasSg; - int Mm2sNumChannels; - int S2MmNumChannels; - int Mm2SBurstSize; - int S2MmBurstSize; - int MicroDmaMode; - int AddrWidth; /**< Address Width */ -} XAxiDma_Config; - - -/***************** Macros (Inline Functions) Definitions *********************/ -/*****************************************************************************/ -/** -* Get Transmit (Tx) Ring ptr -* -* Warning: This has a different API than the LLDMA driver. It now returns -* the pointer to the BD ring. -* -* @param InstancePtr is a pointer to the DMA engine instance to be -* worked on. -* -* @return Pointer to the Tx Ring -* -* @note C-style signature: -* XAxiDma_BdRing * XAxiDma_GetTxRing(XAxiDma * InstancePtr) -* This function is used only when system is configured as SG mode -* -*****************************************************************************/ -#define XAxiDma_GetTxRing(InstancePtr) \ - (&((InstancePtr)->TxBdRing)) - -/*****************************************************************************/ -/** -* Get Receive (Rx) Ring ptr -* -* Warning: This has a different API than the LLDMA driver. It now returns -* the pointer to the BD ring. -* -* @param InstancePtr is a pointer to the DMA engine instance to be -* worked on. -* -* @return Pointer to the Rx Ring -* -* @note -* C-style signature: -* XAxiDma_BdRing * XAxiDma_GetRxRing(XAxiDma * InstancePtr) -* This function is used only when system is configured as SG mode -* -*****************************************************************************/ -#define XAxiDma_GetRxRing(InstancePtr) \ - (&((InstancePtr)->RxBdRing[0])) - -/*****************************************************************************/ -/** -* Get Receive (Rx) Ring ptr of a Index -* -* Warning: This has a different API than the LLDMA driver. It now returns -* the pointer to the BD ring. -* -* @param InstancePtr is a pointer to the DMA engine instance to be -* worked on. -* @param RingIndex is the channel Index. -* -* @return Pointer to the Rx Ring -* -* @note -* C-style signature: -* XAxiDma_BdRing * XAxiDma_GetRxIndexRing(XAxiDma * InstancePtr, - int RingIndex) -* This function is used only when system is configured as SG mode -* -*****************************************************************************/ -#define XAxiDma_GetRxIndexRing(InstancePtr, RingIndex) \ - (&((InstancePtr)->RxBdRing[RingIndex])) - -/*****************************************************************************/ -/** -* This function checks whether system is configured as Simple or -* Scatter Gather mode -* -* @param InstancePtr is a pointer to the DMA engine instance to be -* worked on. -* -* @return -* - TRUE if configured as SG mode -* - FALSE if configured as simple mode -* -* @note None -* -*****************************************************************************/ -#define XAxiDma_HasSg(InstancePtr) ((InstancePtr)->HasSg) ? TRUE : FALSE - -/*****************************************************************************/ -/** - * This function enables interrupts specified by the Mask in specified - * direction, Interrupts that are not in the mask are not affected. - * - * @param InstancePtr is the driver instance we are working on - * @param Mask is the mask for the interrupts to be enabled - * @param Direction is DMA transfer direction, valid values are - * - XAXIDMA_DMA_TO_DEVICE. - * - XAXIDMA_DEVICE_TO_DMA. - * @return None - * - * @note None - * - *****************************************************************************/ -#define XAxiDma_IntrEnable(InstancePtr, Mask, Direction) \ - XAxiDma_WriteReg((InstancePtr)->RegBase + \ - (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_CR_OFFSET, \ - (XAxiDma_ReadReg((InstancePtr)->RegBase + \ - (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_CR_OFFSET)) \ - | (Mask & XAXIDMA_IRQ_ALL_MASK)) - - -/*****************************************************************************/ -/** - * This function gets the mask for the interrupts that are currently enabled - * - * @param InstancePtr is the driver instance we are working on - * @param Direction is DMA transfer direction, valid values are - * - XAXIDMA_DMA_TO_DEVICE. - * - XAXIDMA_DEVICE_TO_DMA. - * - * @return The bit mask for the interrupts that are currently enabled - * - * @note None - * - *****************************************************************************/ -#define XAxiDma_IntrGetEnabled(InstancePtr, Direction) \ - XAxiDma_ReadReg((InstancePtr)->RegBase + \ - (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_CR_OFFSET) &\ - XAXIDMA_IRQ_ALL_MASK) - - - -/*****************************************************************************/ -/** - * This function disables interrupts specified by the Mask. Interrupts that - * are not in the mask are not affected. - * - * @param InstancePtr is the driver instance we are working on - * @param Mask is the mask for the interrupts to be disabled - * @param Direction is DMA transfer direction, valid values are - * - XAXIDMA_DMA_TO_DEVICE. - * - XAXIDMA_DEVICE_TO_DMA. - * @return None - * - * @note None - * - *****************************************************************************/ - #define XAxiDma_IntrDisable(InstancePtr, Mask, Direction) \ - XAxiDma_WriteReg((InstancePtr)->RegBase + \ - (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_CR_OFFSET, \ - (XAxiDma_ReadReg((InstancePtr)->RegBase + \ - (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_CR_OFFSET)) \ - & ~(Mask & XAXIDMA_IRQ_ALL_MASK)) - - -/*****************************************************************************/ -/** - * This function gets the interrupts that are asserted. - * - * @param InstancePtr is the driver instance we are working on - * @param Direction is DMA transfer direction, valid values are - * - XAXIDMA_DMA_TO_DEVICE. - * - XAXIDMA_DEVICE_TO_DMA. - * - * @return The bit mask for the interrupts asserted. - * - * @note None - * - *****************************************************************************/ -#define XAxiDma_IntrGetIrq(InstancePtr, Direction) \ - (XAxiDma_ReadReg((InstancePtr)->RegBase + \ - (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_SR_OFFSET) &\ - XAXIDMA_IRQ_ALL_MASK) - -/*****************************************************************************/ -/** - * This function acknowledges the interrupts that are specified in Mask - * - * @param InstancePtr is the driver instance we are working on - * @param Mask is the mask for the interrupts to be acknowledge - * @param Direction is DMA transfer direction, valid values are - * - XAXIDMA_DMA_TO_DEVICE. - * - XAXIDMA_DEVICE_TO_DMA. - * - * @return None - * - * @note None. - * - *****************************************************************************/ -#define XAxiDma_IntrAckIrq(InstancePtr, Mask, Direction) \ - XAxiDma_WriteReg((InstancePtr)->RegBase + \ - (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_SR_OFFSET, \ - (Mask) & XAXIDMA_IRQ_ALL_MASK) - - - -/************************** Function Prototypes ******************************/ - -/* - * Initialization and control functions in xaxidma.c - */ -XAxiDma_Config *XAxiDma_LookupConfig(u32 DeviceId); -int XAxiDma_CfgInitialize(XAxiDma * InstancePtr, XAxiDma_Config *Config); -void XAxiDma_Reset(XAxiDma * InstancePtr); -int XAxiDma_ResetIsDone(XAxiDma * InstancePtr); -int XAxiDma_Pause(XAxiDma * InstancePtr); -int XAxiDma_Resume(XAxiDma * InstancePtr); -u32 XAxiDma_Busy(XAxiDma *InstancePtr,int Direction); -u32 XAxiDma_SimpleTransfer(XAxiDma *InstancePtr, UINTPTR BuffAddr, u32 Length, - int Direction); -int XAxiDma_SelectKeyHole(XAxiDma *InstancePtr, int Direction, int Select); -int XAxiDma_SelectCyclicMode(XAxiDma *InstancePtr, int Direction, int Select); -int XAxiDma_Selftest(XAxiDma * InstancePtr); -#ifdef __cplusplus -} -#endif - -#endif /* end of protection macro */ -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xaxidma_bd.h b/thirdparty/libxil/include/xilinx/xaxidma_bd.h deleted file mode 100644 index 0b8879ce1..000000000 --- a/thirdparty/libxil/include/xilinx/xaxidma_bd.h +++ /dev/null @@ -1,679 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** - * - * @file xaxidma_bd.h -* @addtogroup axidma_v9_0 -* @{ - * - * Buffer descriptor (BD) management API. - * - * Buffer Descriptors - * - * A BD defines a DMA transaction (see "Transaction" section in xaxidma.h). - * All accesses to a BD go through this set of API. - * - * The XAxiDma_Bd structure defines a BD. The first XAXIDMA_BD_HW_NUM_BYTES - * are shared between hardware and software. - * - * Actual Transfer Length - * - * The actual transfer length for receive could be smaller than the requested - * transfer length. The hardware sets the actual transfer length in the - * completed BD. The API to retrieve the actual transfer length is - * XAxiDma_GetActualLength(). - * - * User IP words - * - * There are 5 user IP words in each BD. - * - * If hardware does not have the StsCntrl stream built in, then these words - * are not usable. Retrieving these words get a NULL pointer and setting - * these words results an error. - * - * Performance - * - * BDs are typically in a non-cached memory space. Reducing the number of - * I/O operations to BDs can improve overall performance of the DMA channel. - * - *
- * MODIFICATION HISTORY:
- *
- * Ver   Who  Date     Changes
- * ----- ---- -------- ------------------------------------------------------
- * 1.00a jz   05/18/10 First release
- * 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
- *                     updated tcl file, added xaxidma_porting_guide.h
- * 3.00a jz   11/22/10 Support IP core parameters change
- * 5.00a srt  08/25/11 Changed Cache Macros to have a common API for Zynq
- *		           and Microblaze.
- * 6.00a srt  01/24/12 Added APIs to support Multi-Channel DMA:
- *			XAxiDma_BdSetTId()
- *			XAxiDma_BdGetTId()
- *			XAxiDma_BdSetTDest()
- *			XAxiDma_BdGetTDest()
- *			XAxiDma_BdSetTUser()
- *			XAxiDma_BdGetTUser()
- *			XAxiDma_BdSetARCache()
- *			XAxiDma_BdGetARCache()
- *			XAxiDma_BdSetARUser()
- *			XAxiDma_BdGetARUser()
- *			XAxiDma_BdSetStride()
- *			XAxiDma_BdGetStride()
- *			XAxiDma_BdSetVSize()
- *			XAxiDma_BdGetVSize()
- *			- Changed APIs
- *			XAxiDma_BdGetActualLength(BdPtr, LengthMask)
- *			XAxiDma_BdGetLength(BdPtr, LengthMask)
- *			XAxiDma_BdSetLength(XAxiDma_Bd* BdPtr,
- *					u32 LenBytes, u32 LengthMask)
- * 7.01a srt  10/26/12  Changed the logic of MCDMA BD fields Set APIs, to
- *			clear the field first and set it.
- * 8.0   srt  01/29/14 Added support for Micro DMA Mode.
- *
- * 
- *****************************************************************************/ - -#ifndef XAXIDMA_BD_H_ /* To prevent circular inclusions */ -#define XAXIDMA_BD_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/***************************** Include Files *********************************/ - -#include "xaxidma_hw.h" -#include "xstatus.h" -#include "xdebug.h" -#include "xil_cache.h" - -#ifdef __MICROBLAZE__ -#include "xenv.h" -#else -#include -#endif - -/************************** Constant Definitions *****************************/ - -/**************************** Type Definitions *******************************/ - -/** - * The XAxiDma_Bd is the type for a buffer descriptor (BD). - */ - -typedef UINTPTR XAxiDma_Bd[XAXIDMA_BD_NUM_WORDS]; - - -/***************** Macros (Inline Functions) Definitions *********************/ - -/****************************************************************************** - * Define methods to flush and invalidate cache for BDs should they be - * located in cached memory. - *****************************************************************************/ -#ifdef __aarch64__ -#define XAXIDMA_CACHE_FLUSH(BdPtr) -#define XAXIDMA_CACHE_INVALIDATE(BdPtr) -#else -#define XAXIDMA_CACHE_FLUSH(BdPtr) \ - Xil_DCacheFlushRange((UINTPTR)(BdPtr), XAXIDMA_BD_HW_NUM_BYTES) - -#define XAXIDMA_CACHE_INVALIDATE(BdPtr) \ - Xil_DCacheInvalidateRange((UINTPTR)(BdPtr), XAXIDMA_BD_HW_NUM_BYTES) -#endif - -/*****************************************************************************/ -/** -* -* Read the given Buffer Descriptor word. -* -* @param BaseAddress is the base address of the BD to read -* @param Offset is the word offset to be read -* -* @return The 32-bit value of the field -* -* @note -* C-style signature: -* u32 XAxiDma_BdRead(u32 BaseAddress, u32 Offset) -* -******************************************************************************/ -#define XAxiDma_BdRead(BaseAddress, Offset) \ - (*(u32 *)((UINTPTR)((void *)(BaseAddress)) + (u32)(Offset))) - -/*****************************************************************************/ -/** -* -* Write the given Buffer Descriptor word. -* -* @param BaseAddress is the base address of the BD to write -* @param Offset is the word offset to be written -* @param Data is the 32-bit value to write to the field -* -* @return None. -* -* @note -* C-style signature: -* void XAxiDma_BdWrite(u32 BaseAddress, u32 RegOffset, u32 Data) -* -******************************************************************************/ -#define XAxiDma_BdWrite(BaseAddress, Offset, Data) \ - (*(u32 *)((UINTPTR)(void *)(BaseAddress) + (u32)(Offset))) = (u32)(Data) - -/*****************************************************************************/ -/** - * Zero out BD specific fields. BD fields that are for the BD ring or for the - * system hardware build information are not touched. - * - * @param BdPtr is the BD to operate on - * - * @return None - * - * @note - * C-style signature: - * void XAxiDma_BdClear(XAxiDma_Bd* BdPtr) - * - *****************************************************************************/ -#define XAxiDma_BdClear(BdPtr) \ - memset((void *)(((UINTPTR)(BdPtr)) + XAXIDMA_BD_START_CLEAR), 0, \ - XAXIDMA_BD_BYTES_TO_CLEAR) - -/*****************************************************************************/ -/** - * Get the control bits for the BD - * - * @param BdPtr is the BD to operate on - * - * @return The bit mask for the control of the BD - * - * @note - * C-style signature: - * u32 XAxiDma_BdGetCtrl(XAxiDma_Bd* BdPtr) - * - *****************************************************************************/ -#define XAxiDma_BdGetCtrl(BdPtr) \ - (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_CTRL_LEN_OFFSET) \ - & XAXIDMA_BD_CTRL_ALL_MASK) -/*****************************************************************************/ -/** - * Retrieve the status of a BD - * - * @param BdPtr is the BD to operate on - * - * @return Word at offset XAXIDMA_BD_DMASR_OFFSET. Use XAXIDMA_BD_STS_*** - * values defined in xaxidma_hw.h to interpret the returned value - * - * @note - * C-style signature: - * u32 XAxiDma_BdGetSts(XAxiDma_Bd* BdPtr) - * - *****************************************************************************/ -#define XAxiDma_BdGetSts(BdPtr) \ - (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STS_OFFSET) & \ - XAXIDMA_BD_STS_ALL_MASK) -/*****************************************************************************/ -/** - * Retrieve the length field value from the given BD. The returned value is - * the same as what was written with XAxiDma_BdSetLength(). Note that in the - * this value does not reflect the real length of received data. - * See the comments of XAxiDma_BdSetLength() for more details. To obtain the - * actual transfer length, use XAxiDma_BdGetActualLength(). - * - * @param BdPtr is the BD to operate on. - * @param LengthMask is the Maximum Transfer Length. - * - * @return The length value set in the BD. - * - * @note - * C-style signature: - * u32 XAxiDma_BdGetLength(XAxiDma_Bd* BdPtr) - * - *****************************************************************************/ -#define XAxiDma_BdGetLength(BdPtr, LengthMask) \ - (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_CTRL_LEN_OFFSET) & \ - LengthMask) - - -/*****************************************************************************/ -/** - * Set the ID field of the given BD. The ID is an arbitrary piece of data the - * application can associate with a specific BD. - * - * @param BdPtr is the BD to operate on - * @param Id is a 32 bit quantity to set in the BD - * - * @return None - * - * @note - * C-style signature: - * void XAxiDma_BdSetId(XAxiDma_Bd* BdPtr, void Id) - * - *****************************************************************************/ -#define XAxiDma_BdSetId(BdPtr, Id) \ - (XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_ID_OFFSET, (u32)(Id))) - - -/*****************************************************************************/ -/** - * Retrieve the ID field of the given BD previously set with XAxiDma_BdSetId. - * - * @param BdPtr is the BD to operate on - * - * @return None - * - * @note - * C-style signature: - * u32 XAxiDma_BdGetId(XAxiDma_Bd* BdPtr) - * - *****************************************************************************/ -#define XAxiDma_BdGetId(BdPtr) (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_ID_OFFSET)) - -/*****************************************************************************/ -/** - * Get the BD's buffer address - * - * @param BdPtr is the BD to operate on - * - * @return None - * - * @note - * C-style signature: - * u32 XAxiDma_BdGetBufAddr(XAxiDma_Bd* BdPtr) - * - *****************************************************************************/ -#define XAxiDma_BdGetBufAddr(BdPtr) \ - (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_BUFA_OFFSET)) - -/*****************************************************************************/ -/** - * Check whether a BD has completed in hardware. This BD has been submitted - * to hardware. The application can use this function to poll for the - * completion of the BD. - * - * This function may not work if the BD is in cached memory. - * - * @param BdPtr is the BD to check on - * - * @return - * - 0 if not complete - * - XAXIDMA_BD_STS_COMPLETE_MASK if completed, may contain - * XAXIDMA_BD_STS_*_ERR_MASK bits. - * - * @note - * C-style signature: - * int XAxiDma_BdHwCompleted(XAxiDma_Bd* BdPtr) - * - *****************************************************************************/ -#define XAxiDma_BdHwCompleted(BdPtr) \ - (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STS_OFFSET) & \ - XAXIDMA_BD_STS_COMPLETE_MASK) - -/*****************************************************************************/ -/** - * Get the actual transfer length of a BD. The BD has completed in hw. - * - * This function may not work if the BD is in cached memory. - * - * @param BdPtr is the BD to check on - * @param LengthMask is the Maximum Transfer Length. - * - * @return None - * - * @note - * C-style signature: - * int XAxiDma_BdGetActualLength(XAxiDma_Bd* BdPtr) - * - *****************************************************************************/ -#define XAxiDma_BdGetActualLength(BdPtr, LengthMask) \ - (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STS_OFFSET) & \ - LengthMask) - -/*****************************************************************************/ -/** - * Set the TID field of the TX BD. - * Provides a stream identifier and can be used to differentiate between - * multiple streams of data that are being transferred across the same - * interface. - * - * @param BdPtr is the BD to operate on - * @param TId is a 8 bit quantity to set in the BD - * - * @return None - * - * @note - * C-style signature: - * void XAxiDma_BdSetTId(XAxiDma_Bd* BdPtr, void TId) - * - *****************************************************************************/ -#define XAxiDma_BdSetTId(BdPtr, TId) \ -{ \ - u32 val; \ - val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET) & \ - ~XAXIDMA_BD_TID_FIELD_MASK); \ - val |= ((u32)(TId) << XAXIDMA_BD_TID_FIELD_SHIFT); \ - XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_MCCTL_OFFSET, val); \ -} - -/*****************************************************************************/ -/** - * Retrieve the TID field of the RX BD previously set with XAxiDma_BdSetTId. - * - * @param BdPtr is the BD to operate on - * - * @return None - * - * @note - * C-style signature: - * u32 XAxiDma_BdGetTId(XAxiDma_Bd* BdPtr) - * - *****************************************************************************/ -#define XAxiDma_BdGetTId(BdPtr) \ - ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STS_OFFSET)) & \ - XAXIDMA_BD_TID_FIELD_MASK) - -/*****************************************************************************/ -/** - * Set the TDEST field of the TX BD. - * Provides coarse routing information for the data stream. - * - * @param BdPtr is the BD to operate on - * @param TDest is a 8 bit quantity to set in the BD - * - * @return None - * - * @note - * C-style signature: - * void XAxiDma_BdSetTDest(XAxiDma_Bd* BdPtr, void TDest) - * - *****************************************************************************/ -#define XAxiDma_BdSetTDest(BdPtr, TDest) \ -{ \ - u32 val; \ - val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET) & \ - ~XAXIDMA_BD_TDEST_FIELD_MASK); \ - val |= ((u32)(TDest) << XAXIDMA_BD_TDEST_FIELD_SHIFT); \ - XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_MCCTL_OFFSET, val); \ -} - -/*****************************************************************************/ -/** - * Retrieve the TDest field of the RX BD previously set with i - * XAxiDma_BdSetTDest. - * - * @param BdPtr is the BD to operate on - * - * @return None - * - * @note - * C-style signature: - * u32 XAxiDma_BdGetTDest(XAxiDma_Bd* BdPtr) - * - *****************************************************************************/ -#define XAxiDma_BdGetTDest(BdPtr) \ - ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STS_OFFSET)) & \ - XAXIDMA_BD_TDEST_FIELD_MASK) - -/*****************************************************************************/ -/** - * Set the TUSER field of the TX BD. - * User defined sideband signaling. - * - * @param BdPtr is the BD to operate on - * @param TUser is a 8 bit quantity to set in the BD - * - * @return None - * - * @note - * C-style signature: - * void XAxiDma_BdSetTUser(XAxiDma_Bd* BdPtr, void TUser) - * - *****************************************************************************/ -#define XAxiDma_BdSetTUser(BdPtr, TUser) \ -{ \ - u32 val; \ - val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET) & \ - ~XAXIDMA_BD_TUSER_FIELD_MASK); \ - val |= ((u32)(TUser) << XAXIDMA_BD_TUSER_FIELD_SHIFT); \ - XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_MCCTL_OFFSET, val); \ -} - -/*****************************************************************************/ -/** - * Retrieve the TUSER field of the RX BD previously set with - * XAxiDma_BdSetTUser. - * - * @param BdPtr is the BD to operate on - * - * @return None - * - * @note - * C-style signature: - * u32 XAxiDma_BdGetTUser(XAxiDma_Bd* BdPtr) - * - *****************************************************************************/ -#define XAxiDma_BdGetTUser(BdPtr) \ - ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STS_OFFSET)) & \ - XAXIDMA_BD_TUSER_FIELD_MASK) - -/*****************************************************************************/ -/** - * Set the ARCACHE field of the given BD. - * This signal provides additional information about the cacheable - * characteristics of the transfer. - * - * @param BdPtr is the BD to operate on - * @param ARCache is a 8 bit quantity to set in the BD - * - * @return None - * - * @note - * C-style signature: - * void XAxiDma_BdSetARCache(XAxiDma_Bd* BdPtr, void ARCache) - * - *****************************************************************************/ -#define XAxiDma_BdSetARCache(BdPtr, ARCache) \ -{ \ - u32 val; \ - val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET) & \ - ~XAXIDMA_BD_ARCACHE_FIELD_MASK); \ - val |= ((u32)(ARCache) << XAXIDMA_BD_ARCACHE_FIELD_SHIFT); \ - XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_MCCTL_OFFSET, val); \ -} - -/*****************************************************************************/ -/** - * Retrieve the ARCACHE field of the given BD previously set with - * XAxiDma_BdSetARCache. - * - * @param BdPtr is the BD to operate on - * - * @return None - * - * @note - * C-style signature: - * u32 XAxiDma_BdGetARCache(XAxiDma_Bd* BdPtr) - * - *****************************************************************************/ -#define XAxiDma_BdGetARCache(BdPtr) \ - ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET)) & \ - XAXIDMA_BD_ARCACHE_FIELD_MASK) - - -/*****************************************************************************/ -/** - * Set the ARUSER field of the given BD. - * Sideband signals used for user defined information. - * - * @param BdPtr is the BD to operate on - * @param ARUser is a 8 bit quantity to set in the BD - * - * @return None - * - * @note - * C-style signature: - * void XAxiDma_BdSetARUser(XAxiDma_Bd* BdPtr, void ARUser) - * - *****************************************************************************/ -#define XAxiDma_BdSetARUser(BdPtr, ARUser) \ -{ \ - u32 val; \ - val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET) & \ - ~XAXIDMA_BD_ARUSER_FIELD_MASK); \ - val |= ((u32)(ARUser) << XAXIDMA_BD_ARUSER_FIELD_SHIFT); \ - XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_MCCTL_OFFSET, val); \ -} - - -/*****************************************************************************/ -/** - * Retrieve the ARUSER field of the given BD previously set with - * XAxiDma_BdSetARUser. - * - * @param BdPtr is the BD to operate on - * - * @return None - * - * @note - * C-style signature: - * u32 XAxiDma_BdGetARUser(XAxiDma_Bd* BdPtr) - * - *****************************************************************************/ -#define XAxiDma_BdGetARUser(BdPtr) \ - ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET)) & \ - XAXIDMA_BD_ARUSER_FIELD_MASK) - -/*****************************************************************************/ -/** - * Set the STRIDE field of the given BD. - * It is the address distance between the first address of successive - * horizontal reads. - * - * @param BdPtr is the BD to operate on - * @param Stride is a 32 bit quantity to set in the BD - * - * @return None - * - * @note - * C-style signature: - * void XAxiDma_BdSetStride(XAxiDma_Bd* BdPtr, void Stride) - * - *****************************************************************************/ -#define XAxiDma_BdSetStride(BdPtr, Stride) \ -{ \ - u32 val; \ - val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STRIDE_VSIZE_OFFSET) & \ - ~XAXIDMA_BD_STRIDE_FIELD_MASK); \ - val |= ((u32)(Stride) << XAXIDMA_BD_STRIDE_FIELD_SHIFT); \ - XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_STRIDE_VSIZE_OFFSET, val); \ -} - -/*****************************************************************************/ -/** - * Retrieve the STRIDE field of the given BD previously set with - * XAxiDma_BdSetStride. - * - * @param BdPtr is the BD to operate on - * - * @return None - * - * @note - * C-style signature: - * u32 XAxiDma_BdGetStride(XAxiDma_Bd* BdPtr) - * - *****************************************************************************/ -#define XAxiDma_BdGetStride(BdPtr) \ - ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STRIDE_VSIZE_OFFSET)) & \ - XAXIDMA_BD_STRIDE_FIELD_MASK) - -/*****************************************************************************/ -/** - * Set the VSIZE field of the given BD. - * Number of horizontal lines for strided access. - * - * @param BdPtr is the BD to operate on - * @param VSize is a 32 bit quantity to set in the BD - * - * @return None - * - * @note - * C-style signature: - * void XAxiDma_BdSetVSize(XAxiDma_Bd* BdPtr, void VSize) - * - *****************************************************************************/ -#define XAxiDma_BdSetVSize(BdPtr, VSize) \ -{ \ - u32 val; \ - val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STRIDE_VSIZE_OFFSET) & \ - ~XAXIDMA_BD_VSIZE_FIELD_MASK); \ - val |= ((u32)(VSize) << XAXIDMA_BD_VSIZE_FIELD_SHIFT); \ - XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_STRIDE_VSIZE_OFFSET, val); \ -} - -/*****************************************************************************/ -/** - * Retrieve the STRIDE field of the given BD previously set with - * XAxiDma_BdSetVSize. - * - * @param BdPtr is the BD to operate on - * - * @return None - * - * @note - * C-style signature: - * u32 XAxiDma_BdGetVSize(XAxiDma_Bd* BdPtr) - * - *****************************************************************************/ -#define XAxiDma_BdGetVSize(BdPtr) \ - ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STRIDE_VSIZE_OFFSET)) & \ - XAXIDMA_BD_VSIZE_FIELD_MASK) - -/*****************************************************************************/ - -/************************** Function Prototypes ******************************/ - -int XAxiDma_BdSetLength(XAxiDma_Bd* BdPtr, u32 LenBytes, u32 LengthMask); -u32 XAxiDma_BdSetBufAddr(XAxiDma_Bd* BdPtr, UINTPTR Addr); -u32 XAxiDma_BdSetBufAddrMicroMode(XAxiDma_Bd* BdPtr, UINTPTR Addr); -int XAxiDma_BdSetAppWord(XAxiDma_Bd * BdPtr, int Offset, u32 Word); -u32 XAxiDma_BdGetAppWord(XAxiDma_Bd * BdPtr, int Offset, int *Valid); -void XAxiDma_BdSetCtrl(XAxiDma_Bd *BdPtr, u32 Data); - -/* Debug utility - */ -void XAxiDma_DumpBd(XAxiDma_Bd* BdPtr); - -#ifdef __cplusplus -} -#endif - -#endif /* end of protection macro */ -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xaxidma_bdring.h b/thirdparty/libxil/include/xilinx/xaxidma_bdring.h deleted file mode 100644 index 351f65827..000000000 --- a/thirdparty/libxil/include/xilinx/xaxidma_bdring.h +++ /dev/null @@ -1,526 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xaxidma_bdring.h -* @addtogroup axidma_v9_0 -* @{ -* -* This file contains DMA channel related structure and constant definition -* as well as function prototypes. Each DMA channel is managed by a Buffer -* Descriptor ring, and XAxiDma_BdRing is chosen as the symbol prefix used in -* this file. See xaxidma.h for more information on how a BD ring is managed. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who  Date     Changes
-* ----- ---- -------- -------------------------------------------------------
-* 1.00a jz   05/18/10 First release
-* 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
-*                     updated tcl file, added xaxidma_porting_guide.h
-* 3.00a jz   11/22/10 Support IP core parameters change
-* 6.00a srt  01/24/12 Added support for Multi-Channel DMA.
-*		      - New API
-*			* XAxiDma_UpdateBdRingCDesc(XAxiDma_BdRing * RingPtr,
-*						int RingIndex)
-*		      - Changed APIs
-*			* XAxiDma_StartBdRingHw(XAxiDma_BdRing * RingPtr,
-*					int RingIndex)
-*			* XAxiDma_BdRingStart(XAxiDma_BdRing * RingPtr,
-*						 int RingIndex)
-*			* XAxiDma_BdRingToHw(XAxiDma_BdRing * RingPtr,
-*        			int NumBd, XAxiDma_Bd * BdSetPtr, int RingIndex)
-*			* XAxiDma_BdRingDumpRegs(XAxiDma_BdRing * RingPtr,
-*						 int RingIndex)
-*			* XAxiDma_BdRingSnapShotCurrBd(XAxiDma_BdRing * RingPtr,
-*						 int RingIndex)
-* 7.00a srt  06/18/12  All the APIs changed in v6_00_a are reverted back for
-*		       backward compatibility.
-*
-*
-* 
-* -******************************************************************************/ - -#ifndef XAXIDMA_BDRING_H_ /* prevent circular inclusions */ -#define XAXIDMA_BDRING_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/***************************** Include Files *********************************/ - -#include "xstatus.h" -#include "xaxidma_bd.h" - - - -/************************** Constant Definitions *****************************/ -/* State of a DMA channel - */ -#define AXIDMA_CHANNEL_NOT_HALTED 1 -#define AXIDMA_CHANNEL_HALTED 2 - -/* Argument constant to simplify argument setting - */ -#define XAXIDMA_NO_CHANGE 0xFFFFFFFF -#define XAXIDMA_ALL_BDS 0x0FFFFFFF /* 268 Million */ - -/**************************** Type Definitions *******************************/ - -/** Container structure for descriptor storage control. If address translation - * is enabled, then all addresses and pointers excluding FirstBdPhysAddr are - * expressed in terms of the virtual address. - */ -typedef struct { - u32 ChanBase; /**< physical base address*/ - - int IsRxChannel; /**< Is this a receive channel */ - volatile int RunState; /**< Whether channel is running */ - int HasStsCntrlStrm; /**< Whether has stscntrl stream */ - int HasDRE; - int DataWidth; - int Addr_ext; - u32 MaxTransferLen; - - UINTPTR FirstBdPhysAddr; /**< Physical address of 1st BD in list */ - UINTPTR FirstBdAddr; /**< Virtual address of 1st BD in list */ - UINTPTR LastBdAddr; /**< Virtual address of last BD in the list */ - u32 Length; /**< Total size of ring in bytes */ - UINTPTR Separation; /**< Number of bytes between the starting - address of adjacent BDs */ - XAxiDma_Bd *FreeHead; /**< First BD in the free group */ - XAxiDma_Bd *PreHead; /**< First BD in the pre-work group */ - XAxiDma_Bd *HwHead; /**< First BD in the work group */ - XAxiDma_Bd *HwTail; /**< Last BD in the work group */ - XAxiDma_Bd *PostHead; /**< First BD in the post-work group */ - XAxiDma_Bd *BdaRestart; /**< BD to load when channel is started */ - int FreeCnt; /**< Number of allocatable BDs in free group */ - int PreCnt; /**< Number of BDs in pre-work group */ - int HwCnt; /**< Number of BDs in work group */ - int PostCnt; /**< Number of BDs in post-work group */ - int AllCnt; /**< Total Number of BDs for channel */ - int RingIndex; /**< Ring Index */ -} XAxiDma_BdRing; - -/***************** Macros (Inline Functions) Definitions *********************/ - -/*****************************************************************************/ -/** -* Use this macro at initialization time to determine how many BDs will fit -* within the given memory constraints. -* -* The results of this macro can be provided to XAxiDma_BdRingCreate(). -* -* @param Alignment specifies what byte alignment the BDs must fall -* on and must be a power of 2 to get an accurate calculation -* (32, 64, 126,...) -* @param Bytes is the number of bytes to be used to store BDs. -* -* @return Number of BDs that can fit in the given memory area -* -* @note -* C-style signature: -* int XAxiDma_BdRingCntCalc(u32 Alignment, u32 Bytes) -* This function is used only when system is configured as SG mode -* -******************************************************************************/ -#define XAxiDma_BdRingCntCalc(Alignment, Bytes) \ - (uint32_t)((Bytes)/((sizeof(XAxiDma_Bd)+((Alignment)-1))&~((Alignment)-1))) - -/*****************************************************************************/ -/** -* Use this macro at initialization time to determine how many bytes of memory -* are required to contain a given number of BDs at a given alignment. -* -* @param Alignment specifies what byte alignment the BDs must fall on. -* This parameter must be a power of 2 to get an accurate -* calculation (32, 64,128,...) -* @param NumBd is the number of BDs to calculate memory size -* requirements -* -* @return The number of bytes of memory required to create a BD list -* with the given memory constraints. -* -* @note -* C-style signature: -* int XAxiDma_BdRingMemCalc(u32 Alignment, u32 NumBd) -* This function is used only when system is configured as SG mode -* -******************************************************************************/ -#define XAxiDma_BdRingMemCalc(Alignment, NumBd) \ - (int)((sizeof(XAxiDma_Bd)+((Alignment)-1)) & ~((Alignment)-1))*(NumBd) - -/****************************************************************************/ -/** -* Return the total number of BDs allocated by this channel with -* XAxiDma_BdRingCreate(). -* -* @param RingPtr is the BD ring to operate on. -* -* @return The total number of BDs allocated for this channel. -* -* @note -* C-style signature: -* int XAxiDma_BdRingGetCnt(XAxiDma_BdRing* RingPtr) -* This function is used only when system is configured as SG mode -* -*****************************************************************************/ -#define XAxiDma_BdRingGetCnt(RingPtr) ((RingPtr)->AllCnt) - -/****************************************************************************/ -/** -* Return the number of BDs allocatable with XAxiDma_BdRingAlloc() for pre- -* processing. -* -* @param RingPtr is the BD ring to operate on. -* -* @return The number of BDs currently allocatable. -* -* @note -* C-style signature: -* int XAxiDma_BdRingGetFreeCnt(XAxiDma_BdRing* RingPtr) -* This function is used only when system is configured as SG mode -* -*****************************************************************************/ -#define XAxiDma_BdRingGetFreeCnt(RingPtr) ((RingPtr)->FreeCnt) - - -/****************************************************************************/ -/** -* Snap shot the latest BD a BD ring is processing. -* -* @param RingPtr is the BD ring to operate on. -* -* @return None -* -* @note -* C-style signature: -* void XAxiDma_BdRingSnapShotCurrBd(XAxiDma_BdRing* RingPtr) -* This function is used only when system is configured as SG mode -* -*****************************************************************************/ -#define XAxiDma_BdRingSnapShotCurrBd(RingPtr) \ - { \ - if (!RingPtr->IsRxChannel) { \ - (RingPtr)->BdaRestart = (XAxiDma_Bd *) \ - XAxiDma_ReadReg((RingPtr)->ChanBase, \ - XAXIDMA_CDESC_OFFSET); \ - } else { \ - if (!RingPtr->RingIndex) { \ - (RingPtr)->BdaRestart = (XAxiDma_Bd *) \ - XAxiDma_ReadReg( \ - (RingPtr)->ChanBase, \ - XAXIDMA_CDESC_OFFSET); \ - } else { \ - (RingPtr)->BdaRestart = (XAxiDma_Bd *) \ - XAxiDma_ReadReg( \ - (RingPtr)->ChanBase, \ - (XAXIDMA_RX_CDESC0_OFFSET + \ - (RingPtr->RingIndex - 1) * \ - XAXIDMA_RX_NDESC_OFFSET)); \ - } \ - } \ - } - -/****************************************************************************/ -/** -* Get the BD a BD ring is processing. -* -* @param RingPtr is the BD ring to operate on. -* -* @return The current BD that the BD ring is working on -* -* @note -* C-style signature: -* XAxiDma_Bd * XAxiDma_BdRingGetCurrBd(XAxiDma_BdRing* RingPtr) -* This function is used only when system is configured as SG mode -* -*****************************************************************************/ -#define XAxiDma_BdRingGetCurrBd(RingPtr) \ - (XAxiDma_Bd *)XAxiDma_ReadReg((RingPtr)->ChanBase, \ - XAXIDMA_CDESC_OFFSET) \ - -/****************************************************************************/ -/** -* Return the next BD in the ring. -* -* @param RingPtr is the BD ring to operate on. -* @param BdPtr is the current BD. -* -* @return The next BD in the ring relative to the BdPtr parameter. -* -* @note -* C-style signature: -* XAxiDma_Bd *XAxiDma_BdRingNext(XAxiDma_BdRing* RingPtr, -* XAxiDma_Bd *BdPtr) -* This function is used only when system is configured as SG mode -* -*****************************************************************************/ -#define XAxiDma_BdRingNext(RingPtr, BdPtr) \ - (((UINTPTR)(BdPtr) >= (RingPtr)->LastBdAddr) ? \ - (UINTPTR)(RingPtr)->FirstBdAddr : \ - (UINTPTR)((UINTPTR)(BdPtr) + (RingPtr)->Separation)) - -/****************************************************************************/ -/** -* Return the previous BD in the ring. -* -* @param RingPtr is the DMA channel to operate on. -* @param BdPtr is the current BD. -* -* @return The previous BD in the ring relative to the BdPtr parameter. -* -* @note -* C-style signature: -* XAxiDma_Bd *XAxiDma_BdRingPrev(XAxiDma_BdRing* RingPtr, -* XAxiDma_Bd *BdPtr) -* This function is used only when system is configured as SG mode -* -*****************************************************************************/ -#define XAxiDma_BdRingPrev(RingPtr, BdPtr) \ - (((u32)(BdPtr) <= (RingPtr)->FirstBdAddr) ? \ - (XAxiDma_Bd*)(RingPtr)->LastBdAddr : \ - (XAxiDma_Bd*)((u32)(BdPtr) - (RingPtr)->Separation)) - -/****************************************************************************/ -/** -* Retrieve the contents of the channel status register -* -* @param RingPtr is the channel instance to operate on. -* -* @return Current contents of status register -* -* @note -* C-style signature: -* u32 XAxiDma_BdRingGetSr(XAxiDma_BdRing* RingPtr) -* This function is used only when system is configured as SG mode -* -*****************************************************************************/ -#define XAxiDma_BdRingGetSr(RingPtr) \ - XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET) - -/****************************************************************************/ -/** -* Get error bits of a DMA channel -* -* @param RingPtr is the channel instance to operate on. -* -* @return Rrror bits in the status register, they should be interpreted -* with XAXIDMA_ERR_*_MASK defined in xaxidma_hw.h -* -* @note -* C-style signature: -* u32 XAxiDma_BdRingGetError(XAxiDma_BdRing* RingPtr) -* This function is used only when system is configured as SG mode -* -*****************************************************************************/ -#define XAxiDma_BdRingGetError(RingPtr) \ - (XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET) \ - & XAXIDMA_ERR_ALL_MASK) - -/****************************************************************************/ -/** -* Check whether a DMA channel is started, meaning the channel is not halted. -* -* @param RingPtr is the channel instance to operate on. -* -* @return -* - 1 if channel is started -* - 0 otherwise -* -* @note -* C-style signature: -* int XAxiDma_BdRingHwIsStarted(XAxiDma_BdRing* RingPtr) -* -*****************************************************************************/ -#define XAxiDma_BdRingHwIsStarted(RingPtr) \ - ((XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET) \ - & XAXIDMA_HALTED_MASK) ? FALSE : TRUE) - -/****************************************************************************/ -/** -* Check if the current DMA channel is busy with a DMA operation. -* -* @param RingPtr is the channel instance to operate on. -* -* @return -* - 1 if the DMA is busy. -* - 0 otherwise -* -* @note -* C-style signature: -* int XAxiDma_BdRingBusy(XAxiDma_BdRing* RingPtr) -* This function is used only when system is configured as SG mode -* -*****************************************************************************/ -#define XAxiDma_BdRingBusy(RingPtr) \ - (XAxiDma_BdRingHwIsStarted(RingPtr) && \ - ((XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET) \ - & XAXIDMA_IDLE_MASK) ? FALSE : TRUE)) - -/****************************************************************************/ -/** -* Set interrupt enable bits for a channel. This operation will modify the -* XAXIDMA_CR_OFFSET register. -* -* @param RingPtr is the channel instance to operate on. -* @param Mask consists of the interrupt signals to enable.Bits not -* specified in the mask are not affected. -* -* @note -* C-style signature: -* void XAxiDma_BdRingIntEnable(XAxiDma_BdRing* RingPtr, u32 Mask) -* This function is used only when system is configured as SG mode -* -*****************************************************************************/ -#define XAxiDma_BdRingIntEnable(RingPtr, Mask) \ - (XAxiDma_WriteReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET, \ - XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET) \ - | ((Mask) & XAXIDMA_IRQ_ALL_MASK))) - -/****************************************************************************/ -/** -* Get enabled interrupts of a channel. It is in XAXIDMA_CR_OFFSET register. -* -* @param RingPtr is the channel instance to operate on. -* @return Enabled interrupts of a channel. Use XAXIDMA_IRQ_* defined in -* xaxidma_hw.h to interpret this returned value. -* -* @note -* C-style signature: -* u32 XAxiDma_BdRingIntGetEnabled(XAxiDma_BdRing* RingPtr) -* This function is used only when system is configured as SG mode -* -*****************************************************************************/ -#define XAxiDma_BdRingIntGetEnabled(RingPtr) \ - (XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET) \ - & XAXIDMA_IRQ_ALL_MASK) - -/****************************************************************************/ -/** -* Clear interrupt enable bits for a channel. It modifies the -* XAXIDMA_CR_OFFSET register. -* -* @param RingPtr is the channel instance to operate on. -* @param Mask consists of the interrupt signals to disable.Bits not -* specified in the Mask are not affected. -* -* @note -* C-style signature: -* void XAxiDma_BdRingIntDisable(XAxiDma_BdRing* RingPtr, -* u32 Mask) -* This function is used only when system is configured as SG mode -* -*****************************************************************************/ -#define XAxiDma_BdRingIntDisable(RingPtr, Mask) \ - (XAxiDma_WriteReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET, \ - XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET) & \ - ~((Mask) & XAXIDMA_IRQ_ALL_MASK))) - -/****************************************************************************/ -/** -* Retrieve the contents of the channel's IRQ register XAXIDMA_SR_OFFSET. This -* operation can be used to see which interrupts are pending. -* -* @param RingPtr is the channel instance to operate on. -* -* @return Current contents of the IRQ_OFFSET register. Use -* XAXIDMA_IRQ_*** values defined in xaxidma_hw.h to interpret -* the returned value. -* -* @note -* C-style signature: -* u32 XAxiDma_BdRingGetIrq(XAxiDma_BdRing* RingPtr) -* This function is used only when system is configured as SG mode -* -*****************************************************************************/ -#define XAxiDma_BdRingGetIrq(RingPtr) \ - (XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET) \ - & XAXIDMA_IRQ_ALL_MASK) - -/****************************************************************************/ -/** -* Acknowledge asserted interrupts. It modifies XAXIDMA_SR_OFFSET register. -* A mask bit set for an unasserted interrupt has no effect. -* -* @param RingPtr is the channel instance to operate on. -* @param Mask are the interrupt signals to acknowledge -* -* @note -* C-style signature: -* void XAxiDma_BdRingAckIrq(XAxiDma_BdRing* RingPtr) -* This function is used only when system is configured as SG mode -* -*****************************************************************************/ -#define XAxiDma_BdRingAckIrq(RingPtr, Mask) \ - XAxiDma_WriteReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET,\ - (Mask) & XAXIDMA_IRQ_ALL_MASK) - -/************************* Function Prototypes ******************************/ - -/* - * Descriptor ring functions xaxidma_bdring.c - */ -int XAxiDma_StartBdRingHw(XAxiDma_BdRing* RingPtr); -int XAxiDma_UpdateBdRingCDesc(XAxiDma_BdRing* RingPtr); -u32 XAxiDma_BdRingCreate(XAxiDma_BdRing * RingPtr, UINTPTR PhysAddr, - UINTPTR VirtAddr, u32 Alignment, int BdCount); -int XAxiDma_BdRingClone(XAxiDma_BdRing * RingPtr, XAxiDma_Bd * SrcBdPtr); -int XAxiDma_BdRingAlloc(XAxiDma_BdRing * RingPtr, int NumBd, - XAxiDma_Bd ** BdSetPtr); -int XAxiDma_BdRingUnAlloc(XAxiDma_BdRing * RingPtr, int NumBd, - XAxiDma_Bd * BdSetPtr); -int XAxiDma_BdRingToHw(XAxiDma_BdRing * RingPtr, int NumBd, - XAxiDma_Bd * BdSetPtr); -int XAxiDma_BdRingFromHw(XAxiDma_BdRing * RingPtr, int BdLimit, - XAxiDma_Bd ** BdSetPtr); -int XAxiDma_BdRingFree(XAxiDma_BdRing * RingPtr, int NumBd, - XAxiDma_Bd * BdSetPtr); -int XAxiDma_BdRingStart(XAxiDma_BdRing * RingPtr); -int XAxiDma_BdRingSetCoalesce(XAxiDma_BdRing * RingPtr, u32 Counter, u32 Timer); -void XAxiDma_BdRingGetCoalesce(XAxiDma_BdRing * RingPtr, - u32 *CounterPtr, u32 *TimerPtr); - -/* The following functions are for debug only - */ -int XAxiDma_BdRingCheck(XAxiDma_BdRing * RingPtr); -void XAxiDma_BdRingDumpRegs(XAxiDma_BdRing *RingPtr); -#ifdef __cplusplus -} -#endif - -#endif /* end of protection macro */ -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xaxidma_hw.h b/thirdparty/libxil/include/xilinx/xaxidma_hw.h deleted file mode 100644 index cc467a83b..000000000 --- a/thirdparty/libxil/include/xilinx/xaxidma_hw.h +++ /dev/null @@ -1,344 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** - * @file xaxidma_hw.h -* @addtogroup axidma_v9_0 -* @{ - * - * Hardware definition file. It defines the register interface and Buffer - * Descriptor (BD) definitions. - * - *
- * MODIFICATION HISTORY:
- *
- * Ver   Who  Date     Changes
- * ----- ---- -------- -------------------------------------------------------
- * 1.00a jz   05/18/10 First release
- * 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
- *                     updated tcl file, added xaxidma_porting_guide.h
- * 3.00a jz   11/22/10 Support IP core parameters change
- * 4.00a rkv  02/22/11 Added support for simple DMA mode
- * 6.00a srt  01/24/12 Added support for Multi-Channel DMA mode
- * 8.0   srt  01/29/14 Added support for Micro DMA Mode and Cyclic mode of
- *		       operations.
- *
- * 
- * - *****************************************************************************/ - -#ifndef XAXIDMA_HW_H_ /* prevent circular inclusions */ -#define XAXIDMA_HW_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "xil_types.h" -#include "xil_io.h" - -/************************** Constant Definitions *****************************/ - -/** @name DMA Transfer Direction - * @{ - */ -#define XAXIDMA_DMA_TO_DEVICE 0x00 -#define XAXIDMA_DEVICE_TO_DMA 0x01 - - -/** @name Buffer Descriptor Alignment - * @{ - */ -#define XAXIDMA_BD_MINIMUM_ALIGNMENT 0x40 /**< Minimum byte alignment - requirement for descriptors to - satisfy both hardware/software - needs */ -/*@}*/ - -/** @name Micro DMA Buffer Address Alignment - * @{ - */ -#define XAXIDMA_MICROMODE_MIN_BUF_ALIGN 0xFFF /**< Minimum byte alignment - requirement for buffer address - in Micro DMA mode */ -/*@}*/ - -/** @name Maximum transfer length - * This is determined by hardware - * @{ - */ -#define XAXIDMA_MAX_TRANSFER_LEN 0x7FFFFF /* Max length hw supports */ -#define XAXIDMA_MCHAN_MAX_TRANSFER_LEN 0x00FFFF /* Max length MCDMA - hw supports */ -/*@}*/ - -/* Register offset definitions. Register accesses are 32-bit. - */ -/** @name Device registers - * Register sets on TX and RX channels are identical - * @{ - */ -#define XAXIDMA_TX_OFFSET 0x00000000 /**< TX channel registers base - * offset */ -#define XAXIDMA_RX_OFFSET 0x00000030 /**< RX channel registers base - * offset */ - -/* This set of registers are applicable for both channels. Add - * XAXIDMA_TX_OFFSET to get to TX channel, and XAXIDMA_RX_OFFSET to get to RX - * channel - */ -#define XAXIDMA_CR_OFFSET 0x00000000 /**< Channel control */ -#define XAXIDMA_SR_OFFSET 0x00000004 /**< Status */ -#define XAXIDMA_CDESC_OFFSET 0x00000008 /**< Current descriptor pointer */ -#define XAXIDMA_CDESC_MSB_OFFSET 0x0000000C /**< Current descriptor pointer */ -#define XAXIDMA_TDESC_OFFSET 0x00000010 /**< Tail descriptor pointer */ -#define XAXIDMA_TDESC_MSB_OFFSET 0x00000014 /**< Tail descriptor pointer */ -#define XAXIDMA_SRCADDR_OFFSET 0x00000018 /**< Simple mode source address - pointer */ -#define XAXIDMA_SRCADDR_MSB_OFFSET 0x0000001C /**< Simple mode source address - pointer */ -#define XAXIDMA_DESTADDR_OFFSET 0x00000018 /**< Simple mode destination address pointer */ -#define XAXIDMA_DESTADDR_MSB_OFFSET 0x0000001C /**< Simple mode destination address pointer */ -#define XAXIDMA_BUFFLEN_OFFSET 0x00000028 /**< Tail descriptor pointer */ -#define XAXIDMA_SGCTL_OFFSET 0x0000002c /**< SG Control Register */ - -/** Multi-Channel DMA Descriptor Offsets **/ -#define XAXIDMA_RX_CDESC0_OFFSET 0x00000040 /**< Rx Current Descriptor 0 */ -#define XAXIDMA_RX_CDESC0_MSB_OFFSET 0x00000044 /**< Rx Current Descriptor 0 */ -#define XAXIDMA_RX_TDESC0_OFFSET 0x00000048 /**< Rx Tail Descriptor 0 */ -#define XAXIDMA_RX_TDESC0_MSB_OFFSET 0x0000004C /**< Rx Tail Descriptor 0 */ -#define XAXIDMA_RX_NDESC_OFFSET 0x00000020 /**< Rx Next Descriptor Offset */ -/*@}*/ - -/** @name Bitmasks of XAXIDMA_CR_OFFSET register - * @{ - */ -#define XAXIDMA_CR_RUNSTOP_MASK 0x00000001 /**< Start/stop DMA channel */ -#define XAXIDMA_CR_RESET_MASK 0x00000004 /**< Reset DMA engine */ -#define XAXIDMA_CR_KEYHOLE_MASK 0x00000008 /**< Keyhole feature */ -#define XAXIDMA_CR_CYCLIC_MASK 0x00000010 /**< Cyclic Mode */ -/*@}*/ - -/** @name Bitmasks of XAXIDMA_SR_OFFSET register - * - * This register reports status of a DMA channel, including - * run/stop/idle state, errors, and interrupts (note that interrupt - * masks are shared with XAXIDMA_CR_OFFSET register, and are defined - * in the _IRQ_ section. - * - * The interrupt coalescing threshold value and delay counter value are - * also shared with XAXIDMA_CR_OFFSET register, and are defined in a - * later section. - * @{ - */ -#define XAXIDMA_HALTED_MASK 0x00000001 /**< DMA channel halted */ -#define XAXIDMA_IDLE_MASK 0x00000002 /**< DMA channel idle */ -#define XAXIDMA_ERR_INTERNAL_MASK 0x00000010 /**< Datamover internal - * err */ -#define XAXIDMA_ERR_SLAVE_MASK 0x00000020 /**< Datamover slave err */ -#define XAXIDMA_ERR_DECODE_MASK 0x00000040 /**< Datamover decode - * err */ -#define XAXIDMA_ERR_SG_INT_MASK 0x00000100 /**< SG internal err */ -#define XAXIDMA_ERR_SG_SLV_MASK 0x00000200 /**< SG slave err */ -#define XAXIDMA_ERR_SG_DEC_MASK 0x00000400 /**< SG decode err */ -#define XAXIDMA_ERR_ALL_MASK 0x00000770 /**< All errors */ - -/** @name Bitmask for interrupts - * These masks are shared by XAXIDMA_CR_OFFSET register and - * XAXIDMA_SR_OFFSET register - * @{ - */ -#define XAXIDMA_IRQ_IOC_MASK 0x00001000 /**< Completion intr */ -#define XAXIDMA_IRQ_DELAY_MASK 0x00002000 /**< Delay interrupt */ -#define XAXIDMA_IRQ_ERROR_MASK 0x00004000 /**< Error interrupt */ -#define XAXIDMA_IRQ_ALL_MASK 0x00007000 /**< All interrupts */ -/*@}*/ - -/** @name Bitmask and shift for delay and coalesce - * These masks are shared by XAXIDMA_CR_OFFSET register and - * XAXIDMA_SR_OFFSET register - * @{ - */ -#define XAXIDMA_DELAY_MASK 0xFF000000 /**< Delay timeout - * counter */ -#define XAXIDMA_COALESCE_MASK 0x00FF0000 /**< Coalesce counter */ - -#define XAXIDMA_DELAY_SHIFT 24 -#define XAXIDMA_COALESCE_SHIFT 16 -/*@}*/ - - -/* Buffer Descriptor (BD) definitions - */ - -/** @name Buffer Descriptor offsets - * USR* fields are defined by higher level IP. - * setup for EMAC type devices. The first 13 words are used by hardware. - * All words after the 13rd word are for software use only. - * @{ - */ -#define XAXIDMA_BD_NDESC_OFFSET 0x00 /**< Next descriptor pointer */ -#define XAXIDMA_BD_NDESC_MSB_OFFSET 0x04 /**< Next descriptor pointer */ -#define XAXIDMA_BD_BUFA_OFFSET 0x08 /**< Buffer address */ -#define XAXIDMA_BD_BUFA_MSB_OFFSET 0x0C /**< Buffer address */ -#define XAXIDMA_BD_MCCTL_OFFSET 0x10 /**< Multichannel Control Fields */ -#define XAXIDMA_BD_STRIDE_VSIZE_OFFSET 0x14 /**< 2D Transfer Sizes */ -#define XAXIDMA_BD_CTRL_LEN_OFFSET 0x18 /**< Control/buffer length */ -#define XAXIDMA_BD_STS_OFFSET 0x1C /**< Status */ - -#define XAXIDMA_BD_USR0_OFFSET 0x20 /**< User IP specific word0 */ -#define XAXIDMA_BD_USR1_OFFSET 0x24 /**< User IP specific word1 */ -#define XAXIDMA_BD_USR2_OFFSET 0x28 /**< User IP specific word2 */ -#define XAXIDMA_BD_USR3_OFFSET 0x2C /**< User IP specific word3 */ -#define XAXIDMA_BD_USR4_OFFSET 0x30 /**< User IP specific word4 */ - -#define XAXIDMA_BD_ID_OFFSET 0x34 /**< Sw ID */ -#define XAXIDMA_BD_HAS_STSCNTRL_OFFSET 0x38 /**< Whether has stscntrl strm */ -#define XAXIDMA_BD_HAS_DRE_OFFSET 0x3C /**< Whether has DRE */ -#define XAXIDMA_BD_ADDRLEN_OFFSET 0x40 /**< Check for BD Addr */ - -#define XAXIDMA_BD_HAS_DRE_MASK 0xF00 /**< Whether has DRE mask */ -#define XAXIDMA_BD_WORDLEN_MASK 0xFF /**< Whether has DRE mask */ - -#define XAXIDMA_BD_HAS_DRE_SHIFT 8 /**< Whether has DRE shift */ -#define XAXIDMA_BD_WORDLEN_SHIFT 0 /**< Whether has DRE shift */ - -#define XAXIDMA_BD_START_CLEAR 8 /**< Offset to start clear */ -#define XAXIDMA_BD_BYTES_TO_CLEAR 48 /**< BD specific bytes to be - * cleared */ - -#define XAXIDMA_BD_NUM_WORDS 20U /**< Total number of words for - * one BD*/ -#define XAXIDMA_BD_HW_NUM_BYTES 52 /**< Number of bytes hw used */ - -/* The offset of the last app word. - */ -#define XAXIDMA_LAST_APPWORD 4 - -/*@}*/ -#define XAXIDMA_DESC_LSB_MASK (0xFFFFFFC0U) /**< LSB Address mask */ - -/** @name Bitmasks of XAXIDMA_BD_CTRL_OFFSET register - * @{ - */ -#define XAXIDMA_BD_CTRL_TXSOF_MASK 0x08000000 /**< First tx packet */ -#define XAXIDMA_BD_CTRL_TXEOF_MASK 0x04000000 /**< Last tx packet */ -#define XAXIDMA_BD_CTRL_ALL_MASK 0x0C000000 /**< All control bits */ -/*@}*/ - -/** @name Bitmasks of XAXIDMA_BD_STS_OFFSET register - * @{ - */ -#define XAXIDMA_BD_STS_COMPLETE_MASK 0x80000000 /**< Completed */ -#define XAXIDMA_BD_STS_DEC_ERR_MASK 0x40000000 /**< Decode error */ -#define XAXIDMA_BD_STS_SLV_ERR_MASK 0x20000000 /**< Slave error */ -#define XAXIDMA_BD_STS_INT_ERR_MASK 0x10000000 /**< Internal err */ -#define XAXIDMA_BD_STS_ALL_ERR_MASK 0x70000000 /**< All errors */ -#define XAXIDMA_BD_STS_RXSOF_MASK 0x08000000 /**< First rx pkt */ -#define XAXIDMA_BD_STS_RXEOF_MASK 0x04000000 /**< Last rx pkt */ -#define XAXIDMA_BD_STS_ALL_MASK 0xFC000000 /**< All status bits */ -/*@}*/ - -/** @name Bitmasks and shift values for XAXIDMA_BD_MCCTL_OFFSET register - * @{ - */ -#define XAXIDMA_BD_TDEST_FIELD_MASK 0x0000000F -#define XAXIDMA_BD_TID_FIELD_MASK 0x00000F00 -#define XAXIDMA_BD_TUSER_FIELD_MASK 0x000F0000 -#define XAXIDMA_BD_ARCACHE_FIELD_MASK 0x0F000000 -#define XAXIDMA_BD_ARUSER_FIELD_MASK 0xF0000000 - -#define XAXIDMA_BD_TDEST_FIELD_SHIFT 0 -#define XAXIDMA_BD_TID_FIELD_SHIFT 8 -#define XAXIDMA_BD_TUSER_FIELD_SHIFT 16 -#define XAXIDMA_BD_ARCACHE_FIELD_SHIFT 24 -#define XAXIDMA_BD_ARUSER_FIELD_SHIFT 28 - -/** @name Bitmasks and shift values for XAXIDMA_BD_STRIDE_VSIZE_OFFSET register - * @{ - */ -#define XAXIDMA_BD_STRIDE_FIELD_MASK 0x0000FFFF -#define XAXIDMA_BD_VSIZE_FIELD_MASK 0xFFF80000 - -#define XAXIDMA_BD_STRIDE_FIELD_SHIFT 0 -#define XAXIDMA_BD_VSIZE_FIELD_SHIFT 19 - -/**************************** Type Definitions *******************************/ - -/***************** Macros (Inline Functions) Definitions *********************/ - -#define XAxiDma_In32 Xil_In32 -#define XAxiDma_Out32 Xil_Out32 - -/*****************************************************************************/ -/** -* -* Read the given register. -* -* @param BaseAddress is the base address of the device -* @param RegOffset is the register offset to be read -* -* @return The 32-bit value of the register -* -* @note -* C-style signature: -* u32 XAxiDma_ReadReg(u32 BaseAddress, u32 RegOffset) -* -******************************************************************************/ -#define XAxiDma_ReadReg(BaseAddress, RegOffset) \ - XAxiDma_In32((BaseAddress) + (RegOffset)) - -/*****************************************************************************/ -/** -* -* Write the given register. -* -* @param BaseAddress is the base address of the device -* @param RegOffset is the register offset to be written -* @param Data is the 32-bit value to write to the register -* -* @return None. -* -* @note -* C-style signature: -* void XAxiDma_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) -* -******************************************************************************/ -#define XAxiDma_WriteReg(BaseAddress, RegOffset, Data) \ - XAxiDma_Out32((BaseAddress) + (RegOffset), (Data)) - -#ifdef __cplusplus -} -#endif - -#endif -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xaxidma_porting_guide.h b/thirdparty/libxil/include/xilinx/xaxidma_porting_guide.h deleted file mode 100644 index ff10ddc7c..000000000 --- a/thirdparty/libxil/include/xilinx/xaxidma_porting_guide.h +++ /dev/null @@ -1,254 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xaxidma_porting_guide.h -* @addtogroup axidma_v9_0 -* @{ -* -* This is a guide on how to move from using the xlldma driver to use xaxidma -* driver. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who  Date     Changes
-* ----- ---- -------- -------------------------------------------------------
-* 1.00a jz   05/18/10 First release
-* 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
-*                     updated tcl file, added xaxidma_porting_guide.h
-* 4.00a rkv  02/22/11 Added support for simple DMA mode
-* 6.00a srt  03/27/12 Added support for MCDMA mode
-* 7.00a srt  06/18/12 API calls are reverted back for backward compatibility.
-*
-* 
-* -* Overview -* -* The API for xaxidma driver is similar to xlldma driver. The prefix for the -* API functions and structures is XAxiDma_ for the xaxidma driver. -* -* Due to hardware feature changes, signatures of some API functions are a -* little bit different from the xlldma API functions. -* -* We present API functions: -* - That only have prefix changes -* - That have different return type -* - That are new API functions -* - That have been removed -* -* Note that data structures have different prefix of XAxiDma_. Those API -* functions, that have data structures with prefix change, are considered as -* prefix change. -* -* API Functions That Only Have Prefix Changes -* -*
-*         xlldma driver              |         xaxidma driver (upto v5_00_a)
-* -----------------------------------------------------------------------
-*    XLlDma_Reset(...)               |  XAxiDma_Reset(...)
-*    XLlDma_BdRingSnapShotCurrBd(...)|  XAxiDma_BdRingSnapShotCurrBd(...)
-*    XLlDma_BdRingNext(...)          |  XAxiDma_BdRingNext(...)
-*    XLlDma_BdRingPrev(...)          |  XAxiDma_BdRingPrev(...)
-*    XLlDma_BdRingGetSr(...)         |  XAxiDma_BdRingGetSr(...)
-*    XLlDma_BdRingBusy(...)          |  XAxiDma_BdRingBusy(...)
-*    XLlDma_BdRingIntEnable(...)     |  XAxiDma_BdRingIntEnable(...)
-*    XLlDma_BdRingIntDisable(...)    |  XAxiDma_BdRingIntDisable(...)
-*    XLlDma_BdRingIntGetEnabled(...) |  XAxiDma_BdRingIntGetEnabled(...)
-*    XLlDma_BdRingGetIrq(...)        |  XAxiDma_BdRingGetIrq(...)
-*    XLlDma_BdRingAckIrq(...)        |  XAxiDma_BdRingAckIrq(...)
-*    XLlDma_BdRingCreate(...)        |  XAxiDma_BdRingCreate(...)
-*    XLlDma_BdRingClone(...)         |  XAxiDma_BdRingClone(...)
-*    XLlDma_BdRingAlloc(...)         |  XAxiDma_BdRingAlloc(...)
-*    XLlDma_BdRingUnAlloc(...)       |  XAxiDma_BdRingUnAlloc(...)
-*    XLlDma_BdRingToHw(...)          |  XAxiDma_BdRingToHw(...)
-*    XLlDma_BdRingFromHw(...)        |  XAxiDma_BdRingFromHw(...)
-*    XLlDma_BdRingFree(...)          |  XAxiDma_BdRingFree(...)
-*    XLlDma_BdRingStart(...)         |  XAxiDma_BdRingStart(...)
-*    XLlDma_BdRingCheck(...)         |  XAxiDma_BdRingCheck(...)
-*    XLlDma_BdRingSetCoalesce(...)   |  XAxiDma_BdRingSetCoalesce(...)
-*    XLlDma_BdRingGetCoalesce(...)   |  XAxiDma_BdRingGetCoalesce(...)
-*    XLlDma_BdRead(...)              |  XAxiDma_BdRead(...)
-*    XLlDma_BdWrite(...)             |  XAxiDma_BdWrite(...)
-*    XLlDma_BdClear(...)             |  XAxiDma_BdClear(...)
-*    XLlDma_BdSetId(...)             |  XAxiDma_BdSetId(...)
-*    XLlDma_BdGetId(...)             |  XAxiDma_BdGetId(...)
-*    XLlDma_BdGetLength(...)         |  XAxiDma_BdGetLength(...)
-*    XLlDma_BdGetBufAddr(...)        |  XAxiDma_BdGetBufAddr(...)
-*
-*
-* -* API Functions That Have Different Return Type -* -* Due to possible hardware failures, The caller should check the return value -* of the following functions. -* -*
-*         xlldma driver              |         xaxidma driver
-* -----------------------------------------------------------------------
-* void XLlDma_Pause(...)             | int XAxiDma_Pause(...)
-* void XLlDma_Resume(...)            | int XAxiDma_Resume(...)
-* 
-* -* The following functions have return type changed: -* -*
-*         xlldma driver              |         xaxidma driver
-* -----------------------------------------------------------------------
-* XLlDma_BdRing XLlDma_GetRxRing(...)| XAxiDma_BdRing * XAxiDma_GetRxRing(...)
-* XLlDma_BdRing XLlDma_GetTxRing(...)| XAxiDma_BdRing * XAxiDma_GetTxRing(...)
-* u32 XLlDma_BdRingMemCalc(...)      | int XAxiDma_BdRingMemCalc(...)
-* u32 XLlDma_BdRingCntCalc(...)      | int XAxiDma_BdRingCntCalc(...)
-* u32 XLlDma_BdRingGetCnt(...)       | int XAxiDma_BdRingGetCnt(...)
-* u32 XLlDma_BdRingGetFreeCnt(...)   | int XAxiDma_BdRingGetFreeCnt(...)
-* void XLlDma_BdSetLength(...)       | int XAxiDma_BdSetLength(...)
-* void XLlDma_BdSetBufAddr(...)      | int XAxiDma_BdSetBufAddr(...)
-*
-* -* API Functions That Are New API Functions -* -* Now that the AXI DMA core is a standalone core, some new API are intrduced. -* Some other functions are added due to hardware interface change, so to -* replace old API functions. -* -* - XAxiDma_Config *XAxiDma_LookupConfig(u32 DeviceId); -* - int XAxiDma_CfgInitialize(XAxiDma * InstancePtr, XAxiDma_Config *Config); -* - int XAxiDma_ResetIsDone(XAxiDma * InstancePtr); -* - XAxiDma_Bd * XAxiDma_BdRingGetCurrBd(XAxiDma_BdRing* RingPtr); -* - int XAxiDma_BdRingHwIsStarted(XAxiDma_BdRing* RingPtr); -* - void XAxiDma_BdRingDumpRegs(XAxiDma_BdRing *RingPtr); -* - int XAxiDma_StartBdRingHw(XAxiDma_BdRing* RingPtr); -* - void XAxiDma_BdSetCtrl(XAxiDma_Bd *BdPtr, u32 Data); -* - u32 XAxiDma_BdGetCtrl(XAxiDma_Bd* BdPtr); -* - u32 XAxiDma_BdGetSts(XAxiDma_Bd* BdPtr); -* - int XAxiDma_BdHwCompleted(XAxiDma_Bd* BdPtr); -* - int XAxiDma_BdGetActualLength(XAxiDma_Bd* BdPtr); -* - int XAxiDma_BdSetAppWord(XAxiDma_Bd * BdPtr, int Offset, u32 Word); -* - u32 XAxiDma_BdGetAppWord(XAxiDma_Bd * BdPtr, int Offset, int *Valid); -* -* API Functions That Have Been Removed -* -* Please see individual function comments for how to replace the removed API -* function with new API functions. -* -* - void XLlDma_Initialize(XLlDma * InstancePtr, u32 BaseAddress). -* This function is replaced by XAxiDma_LookupConfig()/XAxiDma_CfgInitialize() -* -* - u32 XLlDma_BdRingGetCr(XLlDma_BdRing* RingPtr). -* This is replaced by XAxiDma_BdRingGetError(XAxiDma_BdRing* RingPtr) -* -* - u32 XLlDma_BdRingSetCr(XLlDma_BdRing* RingPtr, u32 Data). -* This function is covered by other API functions: -* - void XAxiDma_BdRingIntEnable(XAxiDma_BdRing* RingPtr, u32 Mask) -* - void XAxiDma_BdRingIntDisable(XAxiDma_BdRing* RingPtr, u32 Mask) -* - int XAxiDma_BdRingSetCoalesce(XAxiDma_BdRing * RingPtr, u32 Counter, -* u32 Timer) -* -* - u32 XLlDma_BdSetStsCtrl(XLlDma_Bd* BdPtr, u32 Data). -* Replaced by XAxiDma_BdSetCtrl(XAxiDma_Bd *BdPtr, u32 Data); -* -* - u32 XLlDma_BdGetStsCtrl(XLlDma_Bd* BdPtr). -* Replaced by XAxiDma_BdGetCtrl(XAxiDma_Bd* BdPtr) and -* XAxiDma_BdGetSts(XAxiDma_Bd* BdPtr). -* -* API Functions That Have Been Added to support simple DMA mode -* -* - u32 XAxiDma_Busy(XAxiDma *InstancePtr,int Direction); -* - int XAxiDma_SimpleTransfer(XAxiDma *InstancePtr, u32 BuffAddr, int Length, -* int Direction); -* - XAxiDma_HasSg(InstancePtr); -* - XAxiDma_IntrEnable(InstancePtr,Mask,Direction); -* - XAxiDma_IntrGetEnabled(InstancePtr, Direction); -* - XAxiDma_IntrDisable(InstancePtr, Mask, Direction); -* - XAxiDma_IntrGetIrq(InstancePtr, Direction); -* - XAxiDma_IntrAckIrq(InstancePtr, Mask, Direction); -* -* For xaxidma driver v6_00_a Multiple Channel Support -* --------------------------------------------------- -* This driver supports Multi-channel mode and accordingly some APIs are -* changed to index multiple channels. Few new APIs are added. -* - Changed APIs -* * XAxiDma_GetRxRing(InstancePtr, RingIndex) -* * XAxiDma_Start(XAxiDma * InstancePtr, int RingIndex) -* * XAxiDma_Started(XAxiDma * InstancePtr, int RingIndex) -* * XAxiDma_Pause(XAxiDma * InstancePtr, int RingIndex) -* * XAxiDma_Resume(XAxiDma * InstancePtr, int RingIndex) -* * XAxiDma_SimpleTransfer(XAxiDma *InstancePtr, -* u32 BuffAddr, u32 Length, -* int Direction, int RingIndex) -* * XAxiDma_StartBdRingHw(XAxiDma_BdRing * RingPtr, -* int RingIndex) -* * XAxiDma_BdRingStart(XAxiDma_BdRing * RingPtr, -* int RingIndex) -* * XAxiDma_BdRingToHw(XAxiDma_BdRing * RingPtr, -* int NumBd, XAxiDma_Bd * BdSetPtr, int RingIndex) -* * XAxiDma_BdRingDumpRegs(XAxiDma_BdRing * RingPtr, -* int RingIndex) -* * XAxiDma_BdRingSnapShotCurrBd(XAxiDma_BdRing * RingPtr, -* int RingIndex) -* * XAxiDma_BdSetLength(XAxiDma_Bd *BdPtr, -* u32 LenBytes, u32 LengthMask) -* * XAxiDma_BdGetActualLength(BdPtr, LengthMask) -* * XAxiDma_BdGetLength(BdPtr, LengthMask) -* -* - New APIs -* * XAxiDma_SelectKeyHole(XAxiDma *InstancePtr, -* int Direction, int Select) -* * XAxiDma_UpdateBdRingCDesc(XAxiDma_BdRing * RingPtr, -* int RingIndex) -* * XAxiDma_BdSetTId() -* * XAxiDma_BdGetTId() -* * XAxiDma_BdSetTDest() -* * XAxiDma_BdGetTDest() -* * XAxiDma_BdSetTUser() -* * XAxiDma_BdGetTUser() -* * XAxiDma_BdSetARCache() -* * XAxiDma_BdGetARCache() -* * XAxiDma_BdSetARUser() -* * XAxiDma_BdGetARUser() -* * XAxiDma_BdSetStride() -* * XAxiDma_BdGetStride() -* * XAxiDma_BdSetVSize() -* * XAxiDma_BdGetVSize() -* For xaxidma driver v7_00_a -* --------------------------------------------------- -* - New API -* * XAxiDma_GetRxIndexRing(InstancePtr, RingIndex) -* -* - Changed APIs -* All the APIs changed in v6_00_a are reverted back for backward -* compatibility. -* -* -******************************************************************************/ -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xaxis_switch.h b/thirdparty/libxil/include/xilinx/xaxis_switch.h deleted file mode 100644 index 604760916..000000000 --- a/thirdparty/libxil/include/xilinx/xaxis_switch.h +++ /dev/null @@ -1,208 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2015 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xaxis_switch.h -* @addtogroup axis_switch_v1_0 -* @{ -* @details -* -* This is the main header file for Xilinx AXI4-Stream Switch Control Router -* core. It is used for routing streams where masters in the system do not know -* final destination address. -* -* Core Features -* -* For a full description of AXI4-Stream Switch Control Router, please see the -* hardware specification. -* -* Software Initialization & Configuration -* -* The application needs to do following steps in order for preparing the -* AXI4-Stream Switch Control Router core to be ready. -* -* - Call XAxisScr_LookupConfig using a device ID to find the core -* configuration. -* - Call XAxisScr_CfgInitialize to initialize the device and the driver -* instance associated with it. -* -* Interrupts -* -* This driver does not have interrupt mechanism. -* -* Virtual Memory -* -* This driver supports Virtual Memory. The RTOS is responsible for calculating -* the correct device base address in Virtual Memory space. -* -* Threads -* -* This driver is not thread safe. Any needs for threads or thread mutual -* exclusion must be satisfied by the layer above this driver. -* -* Asserts -* -* Asserts are used within all Xilinx drivers to enforce constraints on argument -* values. Asserts can be turned off on a system-wide basis by defining at -* compile time, the NDEBUG identifier. By default, asserts are turned on and it -* is recommended that users leave asserts on during development. -* -* Building the driver -* -* The XAXI4-Stream Switch driver is composed of several source files. This -* allows the user to build and link only those parts of the driver that are -* necessary. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who Date     Changes
-* ----- --- -------- --------------------------------------------------
-* 1.00  sha 01/28/15 Initial release.
-* 
-* -******************************************************************************/ -#ifndef XAXIS_SWITCH_H_ -#define XAXIS_SWITCH_H_ /**< Prevent circular inclusions - * by using protection macros */ - -#ifdef __cplusplus -extern "C" { -#endif - -/***************************** Include Files *********************************/ - -#include "xaxis_switch_hw.h" -#include "xil_assert.h" -#include "xstatus.h" - -/************************** Constant Definitions *****************************/ - - -/**************************** Type Definitions *******************************/ - -/** -* This typedef contains configuration information for the AXI4-Stream Switch -* core. Each AXI4-Stream Switch device should have a configuration structure -* associated. -*/ -typedef struct { - u16 DeviceId; /**< DeviceId is the unique ID of the AXI4- - * Stream Switch core */ - u32 BaseAddress; /**< BaseAddress is the physical base address - * of the core's registers */ - u8 MaxNumSI; /**< Maximum number of Slave interfaces */ - u8 MaxNumMI; /**< Maximum number of Master interfaces */ -} XAxis_Switch_Config; - -/** -* The AXI4-Stream Switch driver instance data. An instance must be allocated -* for each core in use. -*/ -typedef struct { - XAxis_Switch_Config Config; /**< Hardware Configuration */ - u32 IsReady; /**< Core and the driver instance are - * initialized */ -} XAxis_Switch; - -/***************** Macros (Inline Functions) Definitions *********************/ - -/*****************************************************************************/ -/** -* -* This macro enables register updates. -* -* @param InstancePtr is a pointer to the XAxis_Switch core instance. -* -* @return None. -* -* @note C-style signature: -* void XAxisScr_RegUpdateEnable(XAxis_Switch *InstancePtr) -* -******************************************************************************/ -#define XAxisScr_RegUpdateEnable(InstancePtr) \ - XAxisScr_WriteReg((InstancePtr)->Config.BaseAddress, \ - XAXIS_SCR_CTRL_OFFSET, \ - XAxisScr_ReadReg((InstancePtr)->Config.BaseAddress, \ - XAXIS_SCR_CTRL_OFFSET) | \ - XAXIS_SCR_CTRL_REG_UPDATE_MASK) - -/*****************************************************************************/ -/** -* -* This macro disables register updates. -* -* @param InstancePtr is a pointer to the XAxis_Switch core instance. -* -* @return None. -* -* @note C-style signature: -* void XAxisScr_RegUpdateDisable(XAxis_Switch *InstancePtr) -* -******************************************************************************/ -#define XAxisScr_RegUpdateDisable(InstancePtr) \ - XAxisScr_WriteReg((InstancePtr)->Config.BaseAddress, \ - XAXIS_SCR_CTRL_OFFSET, \ - XAxisScr_ReadReg((InstancePtr)->Config.BaseAddress, \ - XAXIS_SCR_CTRL_OFFSET) & \ - (~XAXIS_SCR_CTRL_REG_UPDATE_MASK)) - -/************************** Function Prototypes ******************************/ - -/* Initialization function in xaxis_switch_sinit.c */ -XAxis_Switch_Config *XAxisScr_LookupConfig(u16 DeviceId); - -/* Initialization and control functions in xaxis_switch.c */ -s32 XAxisScr_CfgInitialize(XAxis_Switch *InstancePtr, - XAxis_Switch_Config *CfgPtr, u32 EffectiveAddr); - -void XAxisScr_MiPortEnable(XAxis_Switch *InstancePtr, u8 MiIndex, - u8 SiIndex); -void XAxisScr_MiPortDisable(XAxis_Switch *InstancePtr, u8 MiIndex); -s32 XAxisScr_IsMiPortEnabled(XAxis_Switch *InstancePtr, u8 MiIndex, - u8 SiIndex); -s32 XAxisScr_IsMiPortDisabled(XAxis_Switch *InstancePtr, u8 MiIndex); -void XAxisScr_MiPortDisableAll(XAxis_Switch *InstancePtr); - -/* Self test function in xaxis_switch_selftest.c */ -s32 XAxisScr_SelfTest(XAxis_Switch *InstancePtr); - -/************************** Variable Declarations ****************************/ - - -#ifdef __cplusplus -} -#endif - -#endif /* End of protection macro */ -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xaxis_switch_hw.h b/thirdparty/libxil/include/xilinx/xaxis_switch_hw.h deleted file mode 100644 index f98227e19..000000000 --- a/thirdparty/libxil/include/xilinx/xaxis_switch_hw.h +++ /dev/null @@ -1,167 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2015 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xaxis_switch_hw.h -* @addtogroup axis_switch_v1_0 -* @{ -* -* This header file contains identifiers and register-level core functions (or -* macros) that can be used to access the Xilinx AXI4-Stream Switch Control -* Router core. -* -* For more information about the operation of this core see the hardware -* specification and documentation in the higher level driver -* xaxis_switch.h file. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who Date     Changes
-* ----- --- -------- --------------------------------------------------
-* 1.00  sha 01/28/15 Initial release.
-* 
-* -******************************************************************************/ -#ifndef XAXIS_SWITCH_HW_H_ -#define XAXIS_SWITCH_HW_H_ /**< Prevent circular inclusions - * by using protection macros */ - -#ifdef __cplusplus -extern "C" { -#endif - -/***************************** Include Files *********************************/ - -#include "xil_io.h" - -/************************** Constant Definitions *****************************/ - -/** @name MI MUX register offsets -* -* @{ -*/ -#define XAXIS_SCR_CTRL_OFFSET 0x000 /**< Control Register offset */ -#define XAXIS_SCR_MI_MUX_START_OFFSET 0x040 /**< Start of MI MUX Register - * offset */ -#define XAXIS_SCR_MI_MUX_END_OFFSET 0x07C /**< End of MI MUX Register - * offset */ - -/*@}*/ - -/** @name MI MUX Control register mask -* @{ -*/ -#define XAXIS_SCR_CTRL_REG_UPDATE_MASK 0x02 /**< Register Update - * mask */ -/*@}*/ - -/** @name MI MUX register mask -* -* It is applicable for MI[0...15] registers. -* @{ -*/ -#define XAXIS_SCR_MI_X_MUX_MASK 0x0F /**< MI MUX mask */ -#define XAXIS_SCR_MI_X_DISABLE_MASK 0x80000000 /**< MI Disable mask */ -#define XAXIS_SCR_MI_X_DISABLE_SHIFT 31 /**< MI Disable shift */ -/*@}*/ - -/**************************** Type Definitions *******************************/ - - -/***************** Macros (Inline Functions) Definitions *********************/ - -/** @name Register access macro definition -* @{ -*/ -#define XAxisScr_In32 Xil_In32 /**< Input Operations */ -#define XAxisScr_Out32 Xil_Out32 /**< Output Operations */ - -/*****************************************************************************/ -/** -* -* This macro reads a value from a AXI4-Stream Switch register. A 32 bit read -* is performed. If the component is implemented in a smaller width, only the -* least significant data is read from the register. The most significant data -* will be read as 0. -* -* @param BaseAddress is the base address of the XAxis_Switch core -* instance. -* @param RegOffset is the register offset of the register (defined at -* the top of this file). -* -* @return The 32-bit value of the register. -* -* @note C-style signature: -* u32 XAxisScr_ReadReg(u32 BaseAddress, u32 RegOffset) -* -******************************************************************************/ -#define XAxisScr_ReadReg(BaseAddress, RegOffset) \ - XAxisScr_In32((BaseAddress) + ((u32)RegOffset)) - -/*****************************************************************************/ -/** -* -* This macro writes a value to a AXI4-Stream Switch register. A 32 bit write -* is performed. If the component is implemented in a smaller width, only the -* least significant data is written. -* -* @param BaseAddress is the base address of the XAxis_Switch core -* instance. -* @param RegOffset is the register offset of the register (defined at -* the top of this file) to be written. -* @param Data is the 32-bit value to write into the register. -* -* @return None. -* -* @note C-style signature: -* void XAxisScr_WriteReg(u32 BaseAddress, u32 RegOffset, -* u32 Data) -* -******************************************************************************/ -#define XAxisScr_WriteReg(BaseAddress, RegOffset, Data) \ - XAxisScr_Out32((BaseAddress) + ((u32)RegOffset), (u32)(Data)) -/*@}*/ - -/************************** Function Prototypes ******************************/ - - -/************************** Variable Declarations ****************************/ - - -#ifdef __cplusplus -} -#endif - -#endif /* end of protection macro */ -/** @} */ \ No newline at end of file diff --git a/thirdparty/libxil/include/xilinx/xbasic_types.h b/thirdparty/libxil/include/xilinx/xbasic_types.h deleted file mode 100644 index 7213c7bcc..000000000 --- a/thirdparty/libxil/include/xilinx/xbasic_types.h +++ /dev/null @@ -1,315 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xbasic_types.h -* @addtogroup common_v1_00_a -* @{ -* -* This file contains basic types for Xilinx software IP. These types do not -* follow the standard naming convention with respect to using the component -* name in front of each name because they are considered to be primitives. -* -* @note -* -* This file contains items which are architecture dependent. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who    Date   Changes
-* ----- ---- -------- -------------------------------------------------------
-* 1.00a rmm  12/14/01 First release
-*       rmm  05/09/03 Added "xassert always" macros to rid ourselves of diab
-*                     compiler warnings
-* 1.00a rpm  11/07/03 Added XNullHandler function as a stub interrupt handler
-* 1.00a rpm  07/21/04 Added XExceptionHandler typedef for processor exceptions
-* 1.00a xd   11/03/04 Improved support for doxygen.
-* 1.00a wre  01/25/07 Added Linux style data types u32, u16, u8, TRUE, FALSE
-* 1.00a rpm  04/02/07 Added ifndef KERNEL around u32, u16, u8 data types
-* 
-* -******************************************************************************/ - -#ifndef XBASIC_TYPES_H /* prevent circular inclusions */ -#define XBASIC_TYPES_H /* by using protection macros */ - -#ifdef __cplusplus -extern "C" { -#endif - - -/***************************** Include Files *********************************/ - - -/************************** Constant Definitions *****************************/ - -#ifndef TRUE -# define TRUE 1 -#endif - -#ifndef FALSE -# define FALSE 0 -#endif - -#ifndef NULL -#define NULL 0 -#endif - -/** Xilinx NULL, TRUE and FALSE legacy support. Deprecated. */ -#define XNULL NULL -#define XTRUE TRUE -#define XFALSE FALSE - - -#define XCOMPONENT_IS_READY 0x11111111 /**< component has been initialized */ -#define XCOMPONENT_IS_STARTED 0x22222222 /**< component has been started */ - -/* the following constants and declarations are for unit test purposes and are - * designed to be used in test applications. - */ -#define XTEST_PASSED 0 -#define XTEST_FAILED 1 - -#define XASSERT_NONE 0 -#define XASSERT_OCCURRED 1 - -extern unsigned int XAssertStatus; -extern void XAssert(char *, int); - -/**************************** Type Definitions *******************************/ - -#include - -/** @name Legacy types - * Deprecated legacy types. - * @{ - */ -typedef uint8_t Xuint8; /**< unsigned 8-bit */ -typedef int8_t Xint8; /**< signed 8-bit */ -typedef uint16_t Xuint16; /**< unsigned 16-bit */ -typedef int16_t Xint16; /**< signed 16-bit */ -typedef uint32_t Xuint32; /**< unsigned 32-bit */ -typedef int32_t Xint32; /**< signed 32-bit */ -typedef float Xfloat32; /**< 32-bit floating point */ -typedef double Xfloat64; /**< 64-bit double precision FP */ -typedef unsigned Xboolean; /**< boolean (XTRUE or XFALSE) */ - -#if !defined __XUINT64__ -typedef struct -{ - Xuint32 Upper; - Xuint32 Lower; -} Xuint64; -#endif - -/** @name New types - * New simple types. - * @{ - */ -#ifndef __KERNEL__ -#ifndef XIL_TYPES_H -typedef Xuint32 u32; -typedef Xuint16 u16; -typedef Xuint8 u8; -#endif -#else -#include -#endif - -/*@}*/ - -/** - * This data type defines an interrupt handler for a device. - * The argument points to the instance of the component - */ -typedef void (*XInterruptHandler) (void *InstancePtr); - -/** - * This data type defines an exception handler for a processor. - * The argument points to the instance of the component - */ -typedef void (*XExceptionHandler) (void *InstancePtr); - -/** - * This data type defines a callback to be invoked when an - * assert occurs. The callback is invoked only when asserts are enabled - */ -typedef void (*XAssertCallback) (char *FilenamePtr, int LineNumber); - -/***************** Macros (Inline Functions) Definitions *********************/ - -/*****************************************************************************/ -/** -* Return the most significant half of the 64 bit data type. -* -* @param x is the 64 bit word. -* -* @return The upper 32 bits of the 64 bit word. -* -* @note None. -* -******************************************************************************/ -#define XUINT64_MSW(x) ((x).Upper) - -/*****************************************************************************/ -/** -* Return the least significant half of the 64 bit data type. -* -* @param x is the 64 bit word. -* -* @return The lower 32 bits of the 64 bit word. -* -* @note None. -* -******************************************************************************/ -#define XUINT64_LSW(x) ((x).Lower) - - -#ifndef NDEBUG - -/*****************************************************************************/ -/** -* This assert macro is to be used for functions that do not return anything -* (void). This in conjunction with the XWaitInAssert boolean can be used to -* accomodate tests so that asserts which fail allow execution to continue. -* -* @param expression is the expression to evaluate. If it evaluates to -* false, the assert occurs. -* -* @return Returns void unless the XWaitInAssert variable is true, in which -* case no return is made and an infinite loop is entered. -* -* @note None. -* -******************************************************************************/ -#define XASSERT_VOID(expression) \ -{ \ - if (expression) \ - { \ - XAssertStatus = XASSERT_NONE; \ - } \ - else \ - { \ - XAssert(__FILE__, __LINE__); \ - XAssertStatus = XASSERT_OCCURRED; \ - return; \ - } \ -} - -/*****************************************************************************/ -/** -* This assert macro is to be used for functions that do return a value. This in -* conjunction with the XWaitInAssert boolean can be used to accomodate tests so -* that asserts which fail allow execution to continue. -* -* @param expression is the expression to evaluate. If it evaluates to false, -* the assert occurs. -* -* @return Returns 0 unless the XWaitInAssert variable is true, in which case -* no return is made and an infinite loop is entered. -* -* @note None. -* -******************************************************************************/ -#define XASSERT_NONVOID(expression) \ -{ \ - if (expression) \ - { \ - XAssertStatus = XASSERT_NONE; \ - } \ - else \ - { \ - XAssert(__FILE__, __LINE__); \ - XAssertStatus = XASSERT_OCCURRED; \ - return 0; \ - } \ -} - -/*****************************************************************************/ -/** -* Always assert. This assert macro is to be used for functions that do not -* return anything (void). Use for instances where an assert should always -* occur. -* -* @return Returns void unless the XWaitInAssert variable is true, in which case -* no return is made and an infinite loop is entered. -* -* @note None. -* -******************************************************************************/ -#define XASSERT_VOID_ALWAYS() \ -{ \ - XAssert(__FILE__, __LINE__); \ - XAssertStatus = XASSERT_OCCURRED; \ - return; \ -} - -/*****************************************************************************/ -/** -* Always assert. This assert macro is to be used for functions that do return -* a value. Use for instances where an assert should always occur. -* -* @return Returns void unless the XWaitInAssert variable is true, in which case -* no return is made and an infinite loop is entered. -* -* @note None. -* -******************************************************************************/ -#define XASSERT_NONVOID_ALWAYS() \ -{ \ - XAssert(__FILE__, __LINE__); \ - XAssertStatus = XASSERT_OCCURRED; \ - return 0; \ -} - - -#else - -#define XASSERT_VOID(expression) -#define XASSERT_VOID_ALWAYS() -#define XASSERT_NONVOID(expression) -#define XASSERT_NONVOID_ALWAYS() -#endif - -/************************** Function Prototypes ******************************/ - -void XAssertSetCallback(XAssertCallback Routine); -void XNullHandler(void *NullParameter); - -#ifdef __cplusplus -} -#endif - -#endif /* end of protection macro */ -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xdebug.h b/thirdparty/libxil/include/xilinx/xdebug.h deleted file mode 100644 index e8047e275..000000000 --- a/thirdparty/libxil/include/xilinx/xdebug.h +++ /dev/null @@ -1,93 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -#ifndef _XDEBUG_H -#define _XDEBUG_H - -#if defined(DEBUG) && !defined(NDEBUG) - -#include - -#ifndef XDEBUG_WARNING -#define XDEBUG_WARNING -#warning DEBUG is enabled -#endif - -#define XDBG_DEBUG_ERROR 0x00000001 /* error condition messages */ -#define XDBG_DEBUG_GENERAL 0x00000002 /* general debug messages */ -#define XDBG_DEBUG_ALL 0xFFFFFFFF /* all debugging data */ - -#define XDBG_DEBUG_FIFO_REG 0x00000100 /* display register reads/writes */ -#define XDBG_DEBUG_FIFO_RX 0x00000101 /* receive debug messages */ -#define XDBG_DEBUG_FIFO_TX 0x00000102 /* transmit debug messages */ -#define XDBG_DEBUG_FIFO_ALL 0x0000010F /* all fifo debug messages */ - -#define XDBG_DEBUG_TEMAC_REG 0x00000400 /* display register reads/writes */ -#define XDBG_DEBUG_TEMAC_RX 0x00000401 /* receive debug messages */ -#define XDBG_DEBUG_TEMAC_TX 0x00000402 /* transmit debug messages */ -#define XDBG_DEBUG_TEMAC_ALL 0x0000040F /* all temac debug messages */ - -#define XDBG_DEBUG_TEMAC_ADPT_RX 0x00000800 /* receive debug messages */ -#define XDBG_DEBUG_TEMAC_ADPT_TX 0x00000801 /* transmit debug messages */ -#define XDBG_DEBUG_TEMAC_ADPT_IOCTL 0x00000802 /* ioctl debug messages */ -#define XDBG_DEBUG_TEMAC_ADPT_MISC 0x00000803 /* debug msg for other routines */ -#define XDBG_DEBUG_TEMAC_ADPT_ALL 0x0000080F /* all temac adapter debug messages */ - -#define xdbg_current_types (XDBG_DEBUG_ERROR) - -#define xdbg_stmnt(x) x - -/* In VxWorks, if _WRS_GNU_VAR_MACROS is defined, special syntax is needed for - * macros that accept variable number of arguments - */ -#if defined(XENV_VXWORKS) && defined(_WRS_GNU_VAR_MACROS) -#define xdbg_printf(type, args...) (((type) & xdbg_current_types) ? printf (## args) : 0) - -#else /* ANSI Syntax */ - -#define xdbg_printf(type, ...) (((type) & xdbg_current_types) ? printf (__VA_ARGS__) : 0) - -#endif - -#else /* defined(DEBUG) && !defined(NDEBUG) */ - -#define xdbg_stmnt(x) - -/* See VxWorks comments above */ -#if defined(XENV_VXWORKS) && defined(_WRS_GNU_VAR_MACROS) -#define xdbg_printf(type, args...) -#else /* ANSI Syntax */ -#define xdbg_printf(...) -#endif - -#endif /* defined(DEBUG) && !defined(NDEBUG) */ - -#endif /* _XDEBUG_H */ diff --git a/thirdparty/libxil/include/xilinx/xenv.h b/thirdparty/libxil/include/xilinx/xenv.h deleted file mode 100644 index 54d24f476..000000000 --- a/thirdparty/libxil/include/xilinx/xenv.h +++ /dev/null @@ -1,191 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xenv.h -* @addtogroup common_v1_00_a -* @{ -* -* Defines common services that are typically found in a host operating. -* environment. This include file simply includes an OS specific file based -* on the compile-time constant BUILD_ENV_*, where * is the name of the target -* environment. -* -* All services are defined as macros. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who  Date     Changes
-* ----- ---- -------- -----------------------------------------------
-* 1.00b ch   10/24/02 Added XENV_LINUX
-* 1.00a rmm  04/17/02 First release
-* 
-* -******************************************************************************/ - -#ifndef XENV_H /* prevent circular inclusions */ -#define XENV_H /* by using protection macros */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Select which target environment we are operating under - */ - -/* VxWorks target environment */ -#if defined XENV_VXWORKS -#include "xenv_vxworks.h" - -/* Linux target environment */ -#elif defined XENV_LINUX -#include "xenv_linux.h" - -/* Unit test environment */ -#elif defined XENV_UNITTEST -#include "ut_xenv.h" - -/* Integration test environment */ -#elif defined XENV_INTTEST -#include "int_xenv.h" - -/* Standalone environment selected */ -#else -#include "xenv_standalone.h" -#endif - - -/* - * The following comments specify the types and macro wrappers that are - * expected to be defined by the target specific header files - */ - -/**************************** Type Definitions *******************************/ - -/*****************************************************************************/ -/** - * - * XENV_TIME_STAMP - * - * A structure that contains a time stamp used by other time stamp macros - * defined below. This structure is processor dependent. - */ - - -/***************** Macros (Inline Functions) Definitions *********************/ - -/*****************************************************************************/ -/** - * - * XENV_MEM_COPY(void *DestPtr, void *SrcPtr, unsigned Bytes) - * - * Copies a non-overlapping block of memory. - * - * @param DestPtr is the destination address to copy data to. - * @param SrcPtr is the source address to copy data from. - * @param Bytes is the number of bytes to copy. - * - * @return None - */ - -/*****************************************************************************/ -/** - * - * XENV_MEM_FILL(void *DestPtr, char Data, unsigned Bytes) - * - * Fills an area of memory with constant data. - * - * @param DestPtr is the destination address to set. - * @param Data contains the value to set. - * @param Bytes is the number of bytes to set. - * - * @return None - */ -/*****************************************************************************/ -/** - * - * XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) - * - * Samples the processor's or external timer's time base counter. - * - * @param StampPtr is the storage for the retrieved time stamp. - * - * @return None - */ - -/*****************************************************************************/ -/** - * - * XENV_TIME_STAMP_DELTA_US(XTIME_STAMP *Stamp1Ptr, XTIME_STAMP* Stamp2Ptr) - * - * Computes the delta between the two time stamps. - * - * @param Stamp1Ptr - First sampled time stamp. - * @param Stamp1Ptr - Sedond sampled time stamp. - * - * @return An unsigned int value with units of microseconds. - */ - -/*****************************************************************************/ -/** - * - * XENV_TIME_STAMP_DELTA_MS(XTIME_STAMP *Stamp1Ptr, XTIME_STAMP* Stamp2Ptr) - * - * Computes the delta between the two time stamps. - * - * @param Stamp1Ptr - First sampled time stamp. - * @param Stamp1Ptr - Sedond sampled time stamp. - * - * @return An unsigned int value with units of milliseconds. - */ - -/*****************************************************************************//** - * - * XENV_USLEEP(unsigned delay) - * - * Delay the specified number of microseconds. - * - * @param delay is the number of microseconds to delay. - * - * @return None - */ - -#ifdef __cplusplus -} -#endif - -#endif /* end of protection macro */ - -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xenv_linux.h b/thirdparty/libxil/include/xilinx/xenv_linux.h deleted file mode 100644 index e1edc618a..000000000 --- a/thirdparty/libxil/include/xilinx/xenv_linux.h +++ /dev/null @@ -1,255 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xenv_linux.h -* @addtogroup common_v1_00_a -* @{ -* -* Defines common services specified by xenv.h. -* -* @note -* This file is not intended to be included directly by driver code. -* Instead, the generic xenv.h file is intended to be included by driver -* code. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who  Date     Changes
-* ----- ---- -------- -----------------------------------------------
-* 1.00a wgr  02/28/07 Added cache handling macros.
-* 1.00a wgr  02/27/07 Simplified code. Deprecated old-style macro names.
-* 1.00a xd   11/03/04 Improved support for doxygen.
-* 1.00a ch   10/24/02 First release
-* 1.10a wgr  03/22/07 Converted to new coding style.
-* 
-* -* -******************************************************************************/ - -#ifndef XENV_LINUX_H -#define XENV_LINUX_H - -#ifdef __cplusplus -extern "C" { -#endif - - -/***************************** Include Files *********************************/ - -#include -#include -#include -#include - - -/****************************************************************************** - * - * MEMCPY / MEMSET related macros. - * - * Those macros are defined to catch legacy code in Xilinx drivers. The - * XENV_MEM_COPY and XENV_MEM_FILL macros were used in early Xilinx driver - * code. They are being replaced by memcpy() and memset() function calls. These - * macros are defined to catch any remaining occurences of those macros. - * - ******************************************************************************/ - -/*****************************************************************************/ -/** - * - * Copies a non-overlapping block of memory. - * - * @param DestPtr - * Destination address to copy data to. - * - * @param SrcPtr - * Source address to copy data from. - * - * @param Bytes - * Number of bytes to copy. - * - * @return None. - * - *****************************************************************************/ - -#define XENV_MEM_COPY(DestPtr, SrcPtr, Bytes) \ - memcpy(DestPtr, SrcPtr, Bytes) -/* do_not_use_XENV_MEM_COPY_use_memcpy_instead */ - - -/*****************************************************************************/ -/** - * - * Fills an area of memory with constant data. - * - * @param DestPtr - * Destination address to copy data to. - * - * @param Data - * Value to set. - * - * @param Bytes - * Number of bytes to copy. - * - * @return None. - * - *****************************************************************************/ - -#define XENV_MEM_FILL(DestPtr, Data, Bytes) \ - memset(DestPtr, Data, Bytes) -/* do_not_use_XENV_MEM_FILL_use_memset_instead */ - - -/****************************************************************************** - * - * TIME related macros - * - ******************************************************************************/ -/** - * A structure that contains a time stamp used by other time stamp macros - * defined below. This structure is processor dependent. - */ -typedef int XENV_TIME_STAMP; - -/*****************************************************************************/ -/** - * - * Time is derived from the 64 bit PPC timebase register - * - * @param StampPtr is the storage for the retrieved time stamp. - * - * @return None. - * - * @note - * - * Signature: void XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) - *

- * This macro must be implemented by the user. - * - *****************************************************************************/ -#define XENV_TIME_STAMP_GET(StampPtr) - -/*****************************************************************************/ -/** - * - * This macro is not yet implemented and always returns 0. - * - * @param Stamp1Ptr is the first sampled time stamp. - * @param Stamp2Ptr is the second sampled time stamp. - * - * @return 0 - * - * @note - * - * This macro must be implemented by the user. - * - *****************************************************************************/ -#define XENV_TIME_STAMP_DELTA_US(Stamp1Ptr, Stamp2Ptr) (0) - -/*****************************************************************************/ -/** - * - * This macro is not yet implemented and always returns 0. - * - * @param Stamp1Ptr is the first sampled time stamp. - * @param Stamp2Ptr is the second sampled time stamp. - * - * @return 0 - * - * @note - * - * This macro must be implemented by the user - * - *****************************************************************************/ -#define XENV_TIME_STAMP_DELTA_MS(Stamp1Ptr, Stamp2Ptr) (0) - -/*****************************************************************************/ -/** - * - * Delay the specified number of microseconds. - * - * @param delay - * Number of microseconds to delay. - * - * @return None. - * - * @note XENV_USLEEP is deprecated. Use udelay() instead. - * - *****************************************************************************/ - -#define XENV_USLEEP(delay) udelay(delay) -/* do_not_use_XENV_MEM_COPY_use_memcpy_instead */ - - -/****************************************************************************** - * - * CACHE handling macros / mappings - * - * The implementation of the cache handling functions can be found in - * arch/microblaze. - * - * These #defines are simple mappings to the Linux API. - * - * The underlying Linux implementation will take care of taking the right - * actions depending on the configuration of the MicroBlaze processor in the - * system. - * - ******************************************************************************/ - -#define XCACHE_ENABLE_DCACHE() __enable_dcache() -#define XCACHE_DISABLE_DCACHE() __disable_dcache() -#define XCACHE_ENABLE_ICACHE() __enable_icache() -#define XCACHE_DISABLE_ICACHE() __disable_icache() - -#define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) invalidate_dcache_range((u32)(Addr), ((u32)(Addr)+(Len))) -#define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) flush_dcache_range((u32)(Addr), ((u32)(Addr)+(Len))) - -#define XCACHE_INVALIDATE_ICACHE_RANGE(Addr, Len) "XCACHE_INVALIDATE_ICACHE_RANGE unsupported" -#define XCACHE_FLUSH_ICACHE_RANGE(Addr, Len) flush_icache_range(Addr, Len) - -#define XCACHE_ENABLE_CACHE() \ - { XCACHE_ENABLE_DCACHE(); XCACHE_ENABLE_ICACHE(); } - -#define XCACHE_DISABLE_CACHE() \ - { XCACHE_DISABLE_DCACHE(); XCACHE_DISABLE_ICACHE(); } - - - -#ifdef __cplusplus -} -#endif - -#endif /* end of protection macro */ - -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xenv_none.h b/thirdparty/libxil/include/xilinx/xenv_none.h deleted file mode 100644 index e0ff47a01..000000000 --- a/thirdparty/libxil/include/xilinx/xenv_none.h +++ /dev/null @@ -1,55 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xenv_none.h -* @addtogroup common_v1_00_a -* @{ -* -* This is a legacy file kept for backwards compatibility. -* -* Please modify your code to #include "xenv_standalone.h" instead. -* -* -******************************************************************************/ - -#warning ******************************************************************** -#warning * -#warning * Use of xenv_none.h deprecated. -#warning * Please include the new xenv_standalone.h file instead. -#warning * -#warning ******************************************************************** - -#include "xenv_standalone.h" - -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xenv_standalone.h b/thirdparty/libxil/include/xilinx/xenv_standalone.h deleted file mode 100644 index 14a83b05c..000000000 --- a/thirdparty/libxil/include/xilinx/xenv_standalone.h +++ /dev/null @@ -1,370 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xenv_standalone.h -* @addtogroup common_v1_00_a -* @{ -* -* Defines common services specified by xenv.h. -* -* @note -* This file is not intended to be included directly by driver code. -* Instead, the generic xenv.h file is intended to be included by driver -* code. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who  Date     Changes
-* ----- ---- -------- -----------------------------------------------
-* 1.00a wgr  02/28/07 Added cache handling macros.
-* 1.00a wgr  02/27/07 Simplified code. Deprecated old-style macro names.
-* 1.00a rmm  01/24/06 Implemented XENV_USLEEP. Assume implementation is being
-*                     used under Xilinx standalone BSP.
-* 1.00a xd   11/03/04 Improved support for doxygen.
-* 1.00a rmm  03/21/02 First release
-* 1.00a wgr  03/22/07 Converted to new coding style.
-* 1.00a rpm  06/29/07 Added udelay macro for standalone
-* 1.00a xd   07/19/07 Included xparameters.h as XPAR_ constants are referred
-*                     to in MICROBLAZE section
-* 1.00a ecm  09/19/08 updated for v7.20 of Microblaze, new functionality
-*
-* 
-* -* -******************************************************************************/ - -#ifndef XENV_STANDALONE_H -#define XENV_STANDALONE_H - -#ifdef __cplusplus -extern "C" { -#endif - -/***************************** Include Files *********************************/ -/****************************************************************************** - * - * Get the processor dependent includes - * - ******************************************************************************/ - -#include - -#if defined __MICROBLAZE__ -# include "mb_interface.h" -# include "xparameters.h" /* XPAR constants used below in MB section */ - -#elif defined __PPC__ -# include "sleep.h" -# include "xcache_l.h" /* also include xcache_l.h for caching macros */ -#endif - -/****************************************************************************** - * - * MEMCPY / MEMSET related macros. - * - * The following are straight forward implementations of memset and memcpy. - * - * NOTE: memcpy may not work if source and target memory area are overlapping. - * - ******************************************************************************/ -/*****************************************************************************/ -/** - * - * Copies a non-overlapping block of memory. - * - * @param DestPtr - * Destination address to copy data to. - * - * @param SrcPtr - * Source address to copy data from. - * - * @param Bytes - * Number of bytes to copy. - * - * @return None. - * - * @note - * The use of XENV_MEM_COPY is deprecated. Use memcpy() instead. - * - * @note - * This implemention MAY BREAK work if source and target memory - * area are overlapping. - * - *****************************************************************************/ - -#define XENV_MEM_COPY(DestPtr, SrcPtr, Bytes) \ - memcpy((void *) DestPtr, (const void *) SrcPtr, (size_t) Bytes) - - - -/*****************************************************************************/ -/** - * - * Fills an area of memory with constant data. - * - * @param DestPtr - * Destination address to copy data to. - * - * @param Data - * Value to set. - * - * @param Bytes - * Number of bytes to copy. - * - * @return None. - * - * @note - * The use of XENV_MEM_FILL is deprecated. Use memset() instead. - * - *****************************************************************************/ - -#define XENV_MEM_FILL(DestPtr, Data, Bytes) \ - memset((void *) DestPtr, (int) Data, (size_t) Bytes) - - - -/****************************************************************************** - * - * TIME related macros - * - ******************************************************************************/ - -/** - * A structure that contains a time stamp used by other time stamp macros - * defined below. This structure is processor dependent. - */ -typedef int XENV_TIME_STAMP; - -/*****************************************************************************/ -/** - * - * Time is derived from the 64 bit PPC timebase register - * - * @param StampPtr is the storage for the retrieved time stamp. - * - * @return None. - * - * @note - * - * Signature: void XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) - *

- * This macro must be implemented by the user. - * - *****************************************************************************/ -#define XENV_TIME_STAMP_GET(StampPtr) - -/*****************************************************************************/ -/** - * - * This macro is not yet implemented and always returns 0. - * - * @param Stamp1Ptr is the first sampled time stamp. - * @param Stamp2Ptr is the second sampled time stamp. - * - * @return 0 - * - * @note - * - * This macro must be implemented by the user. - * - *****************************************************************************/ -#define XENV_TIME_STAMP_DELTA_US(Stamp1Ptr, Stamp2Ptr) (0) - -/*****************************************************************************/ -/** - * - * This macro is not yet implemented and always returns 0. - * - * @param Stamp1Ptr is the first sampled time stamp. - * @param Stamp2Ptr is the second sampled time stamp. - * - * @return 0 - * - * @note - * - * This macro must be implemented by the user. - * - *****************************************************************************/ -#define XENV_TIME_STAMP_DELTA_MS(Stamp1Ptr, Stamp2Ptr) (0) - -/*****************************************************************************/ -/** - * XENV_USLEEP(unsigned delay) - * - * Delay the specified number of microseconds. Not implemented without OS - * support. - * - * @param delay - * Number of microseconds to delay. - * - * @return None. - * - *****************************************************************************/ - -#ifdef __PPC__ -#define XENV_USLEEP(delay) usleep(delay) -#define udelay(delay) usleep(delay) -#else -#define XENV_USLEEP(delay) -#define udelay(delay) -#endif - - -/****************************************************************************** - * - * CACHE handling macros / mappings - * - ******************************************************************************/ -/****************************************************************************** - * - * Processor independent macros - * - ******************************************************************************/ - -#define XCACHE_ENABLE_CACHE() \ - { XCACHE_ENABLE_DCACHE(); XCACHE_ENABLE_ICACHE(); } - -#define XCACHE_DISABLE_CACHE() \ - { XCACHE_DISABLE_DCACHE(); XCACHE_DISABLE_ICACHE(); } - - -/****************************************************************************** - * - * MicroBlaze case - * - * NOTE: Currently the following macros will only work on systems that contain - * only ONE MicroBlaze processor. Also, the macros will only be enabled if the - * system is built using a xparameters.h file. - * - ******************************************************************************/ - -#if defined __MICROBLAZE__ - -/* Check if MicroBlaze data cache was built into the core. - */ -#if (XPAR_MICROBLAZE_USE_DCACHE == 1) -# define XCACHE_ENABLE_DCACHE() microblaze_enable_dcache() -# define XCACHE_DISABLE_DCACHE() microblaze_disable_dcache() -# define XCACHE_INVALIDATE_DCACHE() microblaze_invalidate_dcache() - -# define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) \ - microblaze_invalidate_dcache_range((int)(Addr), (int)(Len)) - -#if (XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK == 1) -# define XCACHE_FLUSH_DCACHE() microblaze_flush_dcache() -# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ - microblaze_flush_dcache_range((int)(Addr), (int)(Len)) -#else -# define XCACHE_FLUSH_DCACHE() microblaze_invalidate_dcache() -# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ - microblaze_invalidate_dcache_range((int)(Addr), (int)(Len)) -#endif /*XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK*/ - -#else -# define XCACHE_ENABLE_DCACHE() -# define XCACHE_DISABLE_DCACHE() -# define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) -# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) -#endif /*XPAR_MICROBLAZE_USE_DCACHE*/ - - -/* Check if MicroBlaze instruction cache was built into the core. - */ -#if (XPAR_MICROBLAZE_USE_ICACHE == 1) -# define XCACHE_ENABLE_ICACHE() microblaze_enable_icache() -# define XCACHE_DISABLE_ICACHE() microblaze_disable_icache() - -# define XCACHE_INVALIDATE_ICACHE() microblaze_invalidate_icache() - -# define XCACHE_INVALIDATE_ICACHE_RANGE(Addr, Len) \ - microblaze_invalidate_icache_range((int)(Addr), (int)(Len)) - -#else -# define XCACHE_ENABLE_ICACHE() -# define XCACHE_DISABLE_ICACHE() -#endif /*XPAR_MICROBLAZE_USE_ICACHE*/ - - -/****************************************************************************** - * - * PowerPC case - * - * Note that the XCACHE_ENABLE_xxx functions are hardcoded to enable a - * specific memory region (0x80000001). Each bit (0-30) in the regions - * bitmask stands for 128MB of memory. Bit 31 stands for the upper 2GB - * range. - * - * regions --> cached address range - * ------------|-------------------------------------------------- - * 0x80000000 | [0, 0x7FFFFFF] - * 0x00000001 | [0xF8000000, 0xFFFFFFFF] - * 0x80000001 | [0, 0x7FFFFFF],[0xF8000000, 0xFFFFFFFF] - * - ******************************************************************************/ - -#elif defined __PPC__ - -#define XCACHE_ENABLE_DCACHE() XCache_EnableDCache(0x80000001) -#define XCACHE_DISABLE_DCACHE() XCache_DisableDCache() -#define XCACHE_ENABLE_ICACHE() XCache_EnableICache(0x80000001) -#define XCACHE_DISABLE_ICACHE() XCache_DisableICache() - -#define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) \ - XCache_InvalidateDCacheRange((unsigned int)(Addr), (unsigned)(Len)) - -#define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ - XCache_FlushDCacheRange((unsigned int)(Addr), (unsigned)(Len)) - -#define XCACHE_INVALIDATE_ICACHE() XCache_InvalidateICache() - - -/****************************************************************************** - * - * Unknown processor / architecture - * - ******************************************************************************/ - -#else -/* #error "Unknown processor / architecture. Must be MicroBlaze or PowerPC." */ -#endif - - -#ifdef __cplusplus -} -#endif - -#endif /* #ifndef XENV_STANDALONE_H */ - -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xenv_vxworks.h b/thirdparty/libxil/include/xilinx/xenv_vxworks.h deleted file mode 100644 index 1254a6bdc..000000000 --- a/thirdparty/libxil/include/xilinx/xenv_vxworks.h +++ /dev/null @@ -1,272 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xenv_vxworks.h -* @addtogroup common_v1_00_a -* @{ -* -* Defines common services specified by xenv.h. -* -* @note -* This file is not intended to be included directly by driver code. -* Instead, the generic xenv.h file is intended to be included by driver -* code. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who  Date     Changes
-* ----- ---- -------- -----------------------------------------------
-* 1.00a wgr  02/28/07 Added cache handling macros.
-* 1.00a wgr  02/27/07 Simplified code. Deprecated old-style macro names.
-* 1.00a xd   11/03/04 Improved support for doxygen.
-*       rmm  09/13/03 CR 177068: Fix compiler warning in XENV_MEM_FILL
-*       rmm  10/24/02 Added XENV_USLEEP macro
-* 1.00a rmm  07/16/01 First release
-* 1.10a wgr  03/22/07 Converted to new coding style.
-* 
-* -* -******************************************************************************/ - -#ifndef XENV_VXWORKS_H -#define XENV_VXWORKS_H - -#ifdef __cplusplus -extern "C" { -#endif - -/***************************** Include Files *********************************/ - -#include "xbasic_types.h" -#include "vxWorks.h" -#include "vxLib.h" -#include "sysLibExtra.h" -#include "cacheLib.h" -#include - -/*****************************************************************************/ -/** - * - * Copies a non-overlapping block of memory. - * - * @param DestPtr - * Destination address to copy data to. - * - * @param SrcPtr - * Source address to copy data from. - * - * @param Bytes - * Number of bytes to copy. - * - * @return None. - * - * @note XENV_MEM_COPY is deprecated. Use memcpy() instead. - * - *****************************************************************************/ - -#define XENV_MEM_COPY(DestPtr, SrcPtr, Bytes) \ - memcpy((void *) DestPtr, (const void *) SrcPtr, (size_t) Bytes) - - -/*****************************************************************************/ -/** - * - * Fills an area of memory with constant data. - * - * @param DestPtr - * Destination address to copy data to. - * - * @param Data - * Value to set. - * - * @param Bytes - * Number of bytes to copy. - * - * @return None. - * - * @note XENV_MEM_FILL is deprecated. Use memset() instead. - * - *****************************************************************************/ - -#define XENV_MEM_FILL(DestPtr, Data, Bytes) \ - memset((void *) DestPtr, (int) Data, (size_t) Bytes) - - -#if (CPU_FAMILY==PPC) -/** - * A structure that contains a time stamp used by other time stamp macros - * defined below. This structure is processor dependent. - */ -typedef struct -{ - u32 TimeBaseUpper; - u32 TimeBaseLower; -} XENV_TIME_STAMP; - -/*****************************************************************************/ -/** - * - * Time is derived from the 64 bit PPC timebase register - * - * @param StampPtr is the storage for the retrieved time stamp. - * - * @return None. - * - * @note - * - * Signature: void XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) - * - *****************************************************************************/ -#define XENV_TIME_STAMP_GET(StampPtr) \ -{ \ - vxTimeBaseGet((UINT32*)&(StampPtr)->TimeBaseUpper, \ - (UINT32*)&(StampPtr)->TimeBaseLower); \ -} - -/*****************************************************************************/ -/** - * - * This macro is not yet implemented and always returns 0. - * - * @param Stamp1Ptr is the first sampled time stamp. - * @param Stamp2Ptr is the second sampled time stamp. - * - * @return 0 - * - * @note None. - * - *****************************************************************************/ -#define XENV_TIME_STAMP_DELTA_US(Stamp1Ptr, Stamp2Ptr) (0) - -/*****************************************************************************/ -/** - * - * This macro is not yet implemented and always returns 0. - * - * @param Stamp1Ptr is the first sampled time stamp. - * @param Stamp2Ptr is the second sampled time stamp. - * - * @return 0 - * - * @note - * - * None. - * - *****************************************************************************/ -#define XENV_TIME_STAMP_DELTA_MS(Stamp1Ptr, Stamp2Ptr) (0) - - -/* For non-PPC systems the above macros are not defined. Generate a error to - * make the developer aware of the problem. - */ -#else -#error "XENV_TIME_STAMP_GET used in a non-PPC system. Aborting." -#endif - - -/*****************************************************************************/ -/** - * - * Delay the specified number of microseconds. - * - * @param delay - * Number of microseconds to delay. - * - * @return None. - * - *****************************************************************************/ - -#define XENV_USLEEP(delay) sysUsDelay(delay) - -#define udelay(delay) sysUsDelay(delay) - - -/****************************************************************************** - * - * CACHE handling macros / mappings - * - ******************************************************************************/ -/****************************************************************************** - * - * PowerPC case - * - ******************************************************************************/ - -#if (CPU_FAMILY==PPC) - -#define XCACHE_ENABLE_CACHE() \ - { XCACHE_ENABLE_DCACHE(); XCACHE_ENABLE_ICACHE(); } - -#define XCACHE_DISABLE_CACHE() \ - { XCACHE_DISABLE_DCACHE(); XCACHE_DISABLE_ICACHE(); } - - -#define XCACHE_ENABLE_DCACHE() cacheEnable(DATA_CACHE) -#define XCACHE_DISABLE_DCACHE() cacheDisable(DATA_CACHE) -#define XCACHE_ENABLE_ICACHE() cacheEnable(INSTRUCTION_CACHE) -#define XCACHE_DISABLE_ICACHE() cacheDisable(INSTRUCTION_CACHE) - - -#define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) \ - cacheInvalidate(DATA_CACHE, (void *)(Addr), (Len)) - -#define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ - cacheFlush(DATA_CACHE, (void *)(Addr), (Len)) - -#define XCACHE_INVALIDATE_ICACHE_RANGE(Addr, Len) \ - cacheInvalidate(INSTRUCTION_CACHE, (void *)(Addr), (Len)) - -#define XCACHE_FLUSH_ICACHE_RANGE(Addr, Len) \ - cacheFlush(INSTRUCTION_CACHE, (void *)(Addr), (Len)) - - -/****************************************************************************** - * - * Unknown processor / architecture - * - ******************************************************************************/ - -#else -#error "Unknown processor / architecture. Must be PPC for VxWorks." -#endif - - -#ifdef __cplusplus -} -#endif - -#endif /* #ifdef XENV_VXWORKS_H */ - -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xhls_dft.h b/thirdparty/libxil/include/xilinx/xhls_dft.h deleted file mode 100644 index 42f6ae241..000000000 --- a/thirdparty/libxil/include/xilinx/xhls_dft.h +++ /dev/null @@ -1,77 +0,0 @@ -// ============================================================== -// File generated by Vivado(TM) HLS - High-Level Synthesis from C, C++ and SystemC -// Version: 2016.1 -// Copyright (C) 1986-2016 Xilinx, Inc. All Rights Reserved. -// -// ============================================================== - -#ifndef XHLS_DFT_H -#define XHLS_DFT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/***************************** Include Files *********************************/ -#include "xil_types.h" -#include "xil_assert.h" -#include "xstatus.h" -#include "xil_io.h" -#include "xhls_dft_hw.h" - -/**************************** Type Definitions ******************************/ -typedef struct { - u16 DeviceId; - u32 Ctrl_BaseAddress; -} XHls_dft_Config; - -typedef struct { - u32 Ctrl_BaseAddress; - u32 IsReady; -} XHls_dft; - -/***************** Macros (Inline Functions) Definitions *********************/ -#define XHls_dft_WriteReg(BaseAddress, RegOffset, Data) \ - Xil_Out32((BaseAddress) + (RegOffset), (u32)(Data)) -#define XHls_dft_ReadReg(BaseAddress, RegOffset) \ - Xil_In32((BaseAddress) + (RegOffset)) - -/************************** Function Prototypes *****************************/ -int XHls_dft_Initialize(XHls_dft *InstancePtr, u16 DeviceId); -XHls_dft_Config* XHls_dft_LookupConfig(u16 DeviceId); -int XHls_dft_CfgInitialize(XHls_dft *InstancePtr, XHls_dft_Config *ConfigPtr); - -void XHls_dft_Start(XHls_dft *InstancePtr); -u32 XHls_dft_IsDone(XHls_dft *InstancePtr); -u32 XHls_dft_IsIdle(XHls_dft *InstancePtr); -u32 XHls_dft_IsReady(XHls_dft *InstancePtr); -void XHls_dft_EnableAutoRestart(XHls_dft *InstancePtr); -void XHls_dft_DisableAutoRestart(XHls_dft *InstancePtr); - -void XHls_dft_Set_num_harmonics_V(XHls_dft *InstancePtr, u32 Data); -u32 XHls_dft_Get_num_harmonics_V(XHls_dft *InstancePtr); -void XHls_dft_Set_decimation_V(XHls_dft *InstancePtr, u32 Data); -u32 XHls_dft_Get_decimation_V(XHls_dft *InstancePtr); -u32 XHls_dft_Get_fharmonics_BaseAddress(XHls_dft *InstancePtr); -u32 XHls_dft_Get_fharmonics_HighAddress(XHls_dft *InstancePtr); -u32 XHls_dft_Get_fharmonics_TotalBytes(XHls_dft *InstancePtr); -u32 XHls_dft_Get_fharmonics_BitWidth(XHls_dft *InstancePtr); -u32 XHls_dft_Get_fharmonics_Depth(XHls_dft *InstancePtr); -u32 XHls_dft_Write_fharmonics_Words(XHls_dft *InstancePtr, int offset, int *data, int length); -u32 XHls_dft_Read_fharmonics_Words(XHls_dft *InstancePtr, int offset, int *data, int length); -u32 XHls_dft_Write_fharmonics_Bytes(XHls_dft *InstancePtr, int offset, char *data, int length); -u32 XHls_dft_Read_fharmonics_Bytes(XHls_dft *InstancePtr, int offset, char *data, int length); - -void XHls_dft_InterruptGlobalEnable(XHls_dft *InstancePtr); -void XHls_dft_InterruptGlobalDisable(XHls_dft *InstancePtr); -void XHls_dft_InterruptEnable(XHls_dft *InstancePtr, u32 Mask); -void XHls_dft_InterruptDisable(XHls_dft *InstancePtr, u32 Mask); -void XHls_dft_InterruptClear(XHls_dft *InstancePtr, u32 Mask); -u32 XHls_dft_InterruptGetEnabled(XHls_dft *InstancePtr); -u32 XHls_dft_InterruptGetStatus(XHls_dft *InstancePtr); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/thirdparty/libxil/include/xilinx/xhls_dft_hw.h b/thirdparty/libxil/include/xilinx/xhls_dft_hw.h deleted file mode 100644 index ff3cedc18..000000000 --- a/thirdparty/libxil/include/xilinx/xhls_dft_hw.h +++ /dev/null @@ -1,52 +0,0 @@ -// ============================================================== -// File generated by Vivado(TM) HLS - High-Level Synthesis from C, C++ and SystemC -// Version: 2016.1 -// Copyright (C) 1986-2016 Xilinx, Inc. All Rights Reserved. -// -// ============================================================== - -// ctrl -// 0x00 : Control signals -// bit 0 - ap_start (Read/Write/COH) -// bit 1 - ap_done (Read/COR) -// bit 2 - ap_idle (Read) -// bit 3 - ap_ready (Read) -// bit 7 - auto_restart (Read/Write) -// others - reserved -// 0x04 : Global Interrupt Enable Register -// bit 0 - Global Interrupt Enable (Read/Write) -// others - reserved -// 0x08 : IP Interrupt Enable Register (Read/Write) -// bit 0 - Channel 0 (ap_done) -// bit 1 - Channel 1 (ap_ready) -// others - reserved -// 0x0c : IP Interrupt Status Register (Read/TOW) -// bit 0 - Channel 0 (ap_done) -// bit 1 - Channel 1 (ap_ready) -// others - reserved -// 0x80 : Data signal of num_harmonics_V -// bit 7~0 - num_harmonics_V[7:0] (Read/Write) -// others - reserved -// 0x84 : reserved -// 0x88 : Data signal of decimation_V -// bit 7~0 - decimation_V[7:0] (Read/Write) -// others - reserved -// 0x8c : reserved -// 0x40 ~ -// 0x7f : Memory 'fharmonics' (16 * 32b) -// Word n : bit [31:0] - fharmonics[n] -// (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on Handshake) - -#define XHLS_DFT_CTRL_ADDR_AP_CTRL 0x00 -#define XHLS_DFT_CTRL_ADDR_GIE 0x04 -#define XHLS_DFT_CTRL_ADDR_IER 0x08 -#define XHLS_DFT_CTRL_ADDR_ISR 0x0c -#define XHLS_DFT_CTRL_ADDR_NUM_HARMONICS_V_DATA 0x80 -#define XHLS_DFT_CTRL_BITS_NUM_HARMONICS_V_DATA 8 -#define XHLS_DFT_CTRL_ADDR_DECIMATION_V_DATA 0x88 -#define XHLS_DFT_CTRL_BITS_DECIMATION_V_DATA 8 -#define XHLS_DFT_CTRL_ADDR_FHARMONICS_BASE 0x40 -#define XHLS_DFT_CTRL_ADDR_FHARMONICS_HIGH 0x7f -#define XHLS_DFT_CTRL_WIDTH_FHARMONICS 32 -#define XHLS_DFT_CTRL_DEPTH_FHARMONICS 16 - diff --git a/thirdparty/libxil/include/xilinx/xil_assert.h b/thirdparty/libxil/include/xilinx/xil_assert.h deleted file mode 100644 index 7ce034201..000000000 --- a/thirdparty/libxil/include/xilinx/xil_assert.h +++ /dev/null @@ -1,85 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2009 - 2015 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xil_assert.h -* -* This file contains assert related functions. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who    Date   Changes
-* ----- ---- -------- -------------------------------------------------------
-* 1.00a hbm  07/14/09 First release
-* 
-* -******************************************************************************/ - -#ifndef XIL_ASSERT_H /* prevent circular inclusions */ -#define XIL_ASSERT_H /* by using protection macros */ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -/***************************** Include Files *********************************/ - - -/************************** Constant Definitions *****************************/ - -/***************** Macros (Inline Functions) Definitions *********************/ - -#define Xil_AssertVoid(expr) \ - ((expr) \ - ? __ASSERT_VOID_CAST (0) \ - : __assert_fail (__STRING(expr), __FILE__, __LINE__, __ASSERT_FUNCTION)) -#define Xil_AssertNonvoid(expr) \ - ((expr) \ - ? __ASSERT_VOID_CAST (0) \ - : __assert_fail (__STRING(expr), __FILE__, __LINE__, __ASSERT_FUNCTION)) -#define Xil_AssertVoidAlways() \ - __assert_fail ("always", __FILE__, __LINE__, __ASSERT_FUNCTION) -#define Xil_AssertNonvoidAlways() \ - __assert_fail ("always", __FILE__, __LINE__, __ASSERT_FUNCTION) - -/************************** Function Prototypes ******************************/ - -#ifdef __cplusplus -} -#endif - -#endif /* end of protection macro */ diff --git a/thirdparty/libxil/include/xilinx/xil_cache.h b/thirdparty/libxil/include/xilinx/xil_cache.h deleted file mode 100644 index a1b68faf0..000000000 --- a/thirdparty/libxil/include/xilinx/xil_cache.h +++ /dev/null @@ -1,71 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2009 - 2015 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xil_cache.h -* -* Contains dummies for cache related functions. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who  Date	 Changes
-* ----- ---- -------- -------------------------------------------------------
-* 1.00a hbm  12/11/09 Initial release
-*
-* 
-* -* @note -* -******************************************************************************/ - -#ifndef XIL_CACHE_VXWORKS_H -#define XIL_CACHE_VXWORKS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define Xil_DCacheEnable() -#define Xil_DCacheDisable() -#define Xil_DCacheInvalidateRange(Addr, Len) -#define Xil_DCacheFlushRange(Addr, Len) -#define Xil_ICacheEnable() -#define Xil_ICacheDisable() -#define Xil_ICacheInvalidateRange(Addr, Len) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/thirdparty/libxil/include/xilinx/xil_io.h b/thirdparty/libxil/include/xilinx/xil_io.h deleted file mode 100644 index ae35ff60b..000000000 --- a/thirdparty/libxil/include/xilinx/xil_io.h +++ /dev/null @@ -1,246 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2009 - 2015 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xil_io.h -* -* This file contains the interface for the general IO component, which -* encapsulates the Input/Output functions for processors that do not -* require any special I/O handling. -* -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who      Date     Changes
-* ----- -------- -------- -----------------------------------------------
-* 1.00a ecm/sdm  10/24/09 First release
-* 1.00a sdm      07/21/10 Added Xil_Htonl/s, Xil_Ntohl/s
-* 3.07a asa	     08/31/12 Added xil_printf.h include
-* 3.08a sgd	     11/05/12 Reverted SYNC macros definitions
-* 
-******************************************************************************/ - -#ifndef XIL_IO_H /* prevent circular inclusions */ -#define XIL_IO_H /* by using protection macros */ - -#ifdef __cplusplus -extern "C" { -#endif - -/***************************** Include Files *********************************/ - -#include "xil_types.h" -//#include "xpseudo_asm.h" -#include "xil_printf.h" - -/************************** Constant Definitions *****************************/ - -/**************************** Type Definitions *******************************/ - -/***************** Macros (Inline Functions) Definitions *********************/ - -#if 0 -# define SYNCHRONIZE_IO dmb() -# define INST_SYNC isb() -# define DATA_SYNC dsb() -#else -# define SYNCHRONIZE_IO -# define INST_SYNC -# define DATA_SYNC -#endif /* __GNUC__ */ - -/*****************************************************************************/ -/** -* -* Perform an big-endian input operation for a 16-bit memory location -* by reading from the specified address and returning the Value read from -* that address. -* -* @param Addr contains the address to perform the input operation at. -* -* @return The Value read from the specified input address with the -* proper endianness. The return Value has the same endianness -* as that of the processor, i.e. if the processor is -* little-engian, the return Value is the byte-swapped Value read -* from the address. -* -* @note None. -* -******************************************************************************/ -#define Xil_In16LE(Addr) Xil_In16((Addr)) - -/*****************************************************************************/ -/** -* -* Perform a big-endian input operation for a 32-bit memory location -* by reading from the specified address and returning the Value read from -* that address. -* -* @param Addr contains the address to perform the input operation at. -* -* @return The Value read from the specified input address with the -* proper endianness. The return Value has the same endianness -* as that of the processor, i.e. if the processor is -* little-engian, the return Value is the byte-swapped Value read -* from the address. -* -* -* @note None. -* -******************************************************************************/ -#define Xil_In32LE(Addr) Xil_In32((Addr)) - -/*****************************************************************************/ -/** -* -* Perform a big-endian output operation for a 16-bit memory location -* by writing the specified Value to the specified address. -* -* @param Addr contains the address to perform the output operation at. -* @param Value contains the Value to be output at the specified address. -* The Value has the same endianness as that of the processor. -* If the processor is little-endian, the byte-swapped Value is -* written to the address. -* -* -* @return None -* -* @note None. -* -******************************************************************************/ -#define Xil_Out16LE(Addr, Value) Xil_Out16((Addr), (Value)) - -/*****************************************************************************/ -/** -* -* Perform a big-endian output operation for a 32-bit memory location -* by writing the specified Value to the specified address. -* -* @param Addr contains the address to perform the output operation at. -* @param Value contains the Value to be output at the specified address. -* The Value has the same endianness as that of the processor. -* If the processor is little-endian, the byte-swapped Value is -* written to the address. -* -* @return None -* -* @note None. -* -******************************************************************************/ -#define Xil_Out32LE(Addr, Value) Xil_Out32((Addr), (Value)) - -/*****************************************************************************/ -/** -* -* Convert a 32-bit number from host byte order to network byte order. -* -* @param Data the 32-bit number to be converted. -* -* @return The converted 32-bit number in network byte order. -* -* @note None. -* -******************************************************************************/ -#define Xil_Htonl(Data) Xil_EndianSwap32((Data)) - -/*****************************************************************************/ -/** -* -* Convert a 16-bit number from host byte order to network byte order. -* -* @param Data the 16-bit number to be converted. -* -* @return The converted 16-bit number in network byte order. -* -* @note None. -* -******************************************************************************/ -#define Xil_Htons(Data) Xil_EndianSwap16((Data)) - -/*****************************************************************************/ -/** -* -* Convert a 32-bit number from network byte order to host byte order. -* -* @param Data the 32-bit number to be converted. -* -* @return The converted 32-bit number in host byte order. -* -* @note None. -* -******************************************************************************/ -#define Xil_Ntohl(Data) Xil_EndianSwap32((Data)) - -/*****************************************************************************/ -/** -* -* Convert a 16-bit number from network byte order to host byte order. -* -* @param Data the 16-bit number to be converted. -* -* @return The converted 16-bit number in host byte order. -* -* @note None. -* -******************************************************************************/ -#define Xil_Ntohs(Data) Xil_EndianSwap16((Data)) - -/************************** Function Prototypes ******************************/ - -/* The following functions allow the software to be transportable across - * processors which may use memory mapped I/O or I/O which is mapped into a - * seperate address space. - */ -u8 Xil_In8(INTPTR Addr); -u16 Xil_In16(INTPTR Addr); -u32 Xil_In32(INTPTR Addr); - -void Xil_Out8(INTPTR Addr, u8 Value); -void Xil_Out16(INTPTR Addr, u16 Value); -void Xil_Out32(INTPTR Addr, u32 Value); - - -u16 Xil_In16BE(INTPTR Addr); -u32 Xil_In32BE(INTPTR Addr); -void Xil_Out16BE(INTPTR Addr, u16 Value); -void Xil_Out32BE(INTPTR Addr, u32 Value); - -u16 Xil_EndianSwap16(u16 Data); -u32 Xil_EndianSwap32(u32 Data); - -#ifdef __cplusplus -} -#endif - -#endif /* end of protection macro */ diff --git a/thirdparty/libxil/include/xilinx/xil_printf.h b/thirdparty/libxil/include/xilinx/xil_printf.h deleted file mode 100644 index a3ecfea50..000000000 --- a/thirdparty/libxil/include/xilinx/xil_printf.h +++ /dev/null @@ -1,43 +0,0 @@ - #ifndef XIL_PRINTF_H - #define XIL_PRINTF_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include -#include "xil_types.h" - -/*----------------------------------------------------*/ -/* Use the following parameter passing structure to */ -/* make xil_printf re-entrant. */ -/*----------------------------------------------------*/ - -struct params_s; - - -/*---------------------------------------------------*/ -/* The purpose of this routine is to output data the */ -/* same as the standard printf function without the */ -/* overhead most run-time libraries involve. Usually */ -/* the printf brings in many kilobytes of code and */ -/* that is unacceptable in most embedded systems. */ -/*---------------------------------------------------*/ - -typedef char8* charptr; -typedef s32 (*func_ptr)(int c); - -#define xil_printf(fmt, ...) printf(fmt, ##__VA_ARGS__) -#define print(ptr) printf("%s", ptr) - -#define outbyte(byte) putc(byte, stdout) -#define inbyte(); getc(stdin) - -#ifdef __cplusplus -} -#endif - -#endif /* end of protection macro */ diff --git a/thirdparty/libxil/include/xilinx/xil_types.h b/thirdparty/libxil/include/xilinx/xil_types.h deleted file mode 100644 index e8b78b7c6..000000000 --- a/thirdparty/libxil/include/xilinx/xil_types.h +++ /dev/null @@ -1,200 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xil_types.h -* -* This file contains basic types for Xilinx software IP. - -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who    Date   Changes
-* ----- ---- -------- -------------------------------------------------------
-* 1.00a hbm  07/14/09 First release
-* 3.03a sdm  05/30/11 Added Xuint64 typedef and XUINT64_MSW/XUINT64_LSW macros
-* 5.00 	pkp  05/29/14 Made changes for 64 bit architecture
-*	srt  07/14/14 Use standard definitions from stdint.h and stddef.h
-*		      Define LONG and ULONG datatypes and mask values
-* 
-* -******************************************************************************/ - -#ifndef XIL_TYPES_H /* prevent circular inclusions */ -#define XIL_TYPES_H /* by using protection macros */ - -#include -#include - -/************************** Constant Definitions *****************************/ - -#ifndef TRUE -# define TRUE 1U -#endif - -#ifndef FALSE -# define FALSE 0U -#endif - -#ifndef NULL -#define NULL 0U -#endif - -#define XIL_COMPONENT_IS_READY 0x11111111U /**< component has been initialized */ -#define XIL_COMPONENT_IS_STARTED 0x22222222U /**< component has been started */ - -/** @name New types - * New simple types. - * @{ - */ -#ifndef __KERNEL__ -#ifndef XBASIC_TYPES_H -/** - * guarded against xbasic_types.h. - */ -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; - -#define __XUINT64__ -typedef struct -{ - u32 Upper; - u32 Lower; -} Xuint64; - - -/*****************************************************************************/ -/** -* Return the most significant half of the 64 bit data type. -* -* @param x is the 64 bit word. -* -* @return The upper 32 bits of the 64 bit word. -* -* @note None. -* -******************************************************************************/ -#define XUINT64_MSW(x) ((x).Upper) - -/*****************************************************************************/ -/** -* Return the least significant half of the 64 bit data type. -* -* @param x is the 64 bit word. -* -* @return The lower 32 bits of the 64 bit word. -* -* @note None. -* -******************************************************************************/ -#define XUINT64_LSW(x) ((x).Lower) - -#endif /* XBASIC_TYPES_H */ - -/** - * xbasic_types.h does not typedef s* or u64 - */ - -typedef char char8; -typedef int8_t s8; -typedef int16_t s16; -typedef int32_t s32; -typedef int64_t s64; -typedef uint64_t u64; -typedef int sint32; - -typedef intptr_t INTPTR; -typedef uintptr_t UINTPTR; -typedef ptrdiff_t PTRDIFF; - -#if !defined(LONG) || !defined(ULONG) -typedef long LONG; -typedef unsigned long ULONG; -#endif - -#define ULONG64_HI_MASK 0xFFFFFFFF00000000U -#define ULONG64_LO_MASK ~ULONG64_HI_MASK - -#else -#include -#endif - - -/** - * This data type defines an interrupt handler for a device. - * The argument points to the instance of the component - */ -typedef void (*XInterruptHandler) (void *InstancePtr); - -/** - * This data type defines an exception handler for a processor. - * The argument points to the instance of the component - */ -typedef void (*XExceptionHandler) (void *InstancePtr); - -/** - * UPPER_32_BITS - return bits 32-63 of a number - * @n: the number we're accessing - * - * A basic shift-right of a 64- or 32-bit quantity. Use this to suppress - * the "right shift count >= width of type" warning when that quantity is - * 32-bits. - */ -#define UPPER_32_BITS(n) ((u32)(((n) >> 16) >> 16)) - -/** - * LOWER_32_BITS - return bits 0-31 of a number - * @n: the number we're accessing - */ -#define LOWER_32_BITS(n) ((u32)(n)) - -/*@}*/ - - -/************************** Constant Definitions *****************************/ - -#ifndef TRUE -#define TRUE 1U -#endif - -#ifndef FALSE -#define FALSE 0U -#endif - -#ifndef NULL -#define NULL 0U -#endif - -#endif /* end of protection macro */ diff --git a/thirdparty/libxil/include/xilinx/xintc.h b/thirdparty/libxil/include/xilinx/xintc.h deleted file mode 100644 index 080f01b51..000000000 --- a/thirdparty/libxil/include/xilinx/xintc.h +++ /dev/null @@ -1,370 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xintc.h -* @addtogroup intc_v3_4 -* @{ -* @details -* -* The Xilinx interrupt controller driver component. This component supports the -* Xilinx interrupt controller. -* -* The interrupt controller driver uses the idea of priority for the various -* handlers. Priority is an integer within the range of 0 and 31 inclusive with -* 0 being the highest priority interrupt source. -* -* The Xilinx interrupt controller supports the following features: -* -* - specific individual interrupt enabling/disabling -* - specific individual interrupt acknowledging -* - attaching specific callback function to handle interrupt source -* - master enable/disable -* - single callback per interrupt or all pending interrupts handled for -* each interrupt of the processor -* -* The acknowledgement of the interrupt within the interrupt controller is -* selectable, either prior to the device's handler being called or after -* the handler is called. This is necessary to support interrupt signal inputs -* which are either edge or level signals. Edge driven interrupt signals -* require that the interrupt is acknowledged prior to the interrupt being -* serviced in order to prevent the loss of interrupts which are occurring -* extremely close together. A level driven interrupt input signal requires -* the interrupt to acknowledged after servicing the interrupt to ensure that -* the interrupt only generates a single interrupt condition. -* -* Details about connecting the interrupt handler of the driver are contained -* in the source file specific to interrupt processing, xintc_intr.c. -* -* This driver is intended to be RTOS and processor independent. It works with -* physical addresses only. Any needs for dynamic memory management, threads -* or thread mutual exclusion, virtual memory, or cache control must be -* satisfied by the layer above this driver. -* -* Interrupt Vector Tables -* -* The interrupt vector table for each interrupt controller device is declared -* statically in xintc_g.c within the configuration data for each instance. -* The device ID of the interrupt controller device is used by the driver as a -* direct index into the configuration data table - to retrieve the vector table -* for an instance of the interrupt controller. The user should populate the -* vector table with handlers and callbacks at run-time using the XIntc_Connect() -* and XIntc_Disconnect() functions. -* -* Each vector table entry corresponds to a device that can generate an -* interrupt. Each entry contains an interrupt handler function and an argument -* to be passed to the handler when an interrupt occurs. The tools default this -* argument to the base address of the interrupting device. Note that the -* device driver interrupt handlers given in this file do not take a base -* address as an argument, but instead take a pointer to the driver instance. -* This means that although the table is created statically, the user must still -* use XIntc_Connect() when the interrupt handler takes an argument other than -* the base address. This is only to say that the existence of the static vector -* tables should not mislead the user into thinking they no longer need to -* register/connect interrupt handlers with this driver. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who  Date     Changes
-* ----- ---- -------- -------------------------------------------------------
-* 1.00a ecm  08/16/01 First release
-* 1.00a rpm  01/09/02 Removed the AckLocation argument from XIntc_Connect().
-*                     This information is now internal in xintc_g.c.
-* 1.00b jhl  02/13/02 Repartitioned the driver for smaller files
-* 1.00b jhl  04/24/02 Made LookupConfig function global and relocated config
-*                     data type
-* 1.00c rpm  10/17/03 New release. Support the static vector table created
-*                     in the xintc_g.c configuration table. Moved vector
-*                     table and options out of instance structure and into
-*                     the configuration table.
-* 1.10c mta  03/21/07 Updated to new coding style
-* 1.11a sv   11/21/07 Updated driver to support access through a DCR bridge
-* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs and _m is removed from
-*		      all the macro names/definitions.
-* 2.01a sdm  04/27/10 Updated the tcl so that the defintions are generated in
-*		      the xparameters.h to know whether the optional registers
-*		      SIE, CIE and IVR are enabled in the HW - Refer CR 555392.
-*		      This driver doesnot make use of these definitions and does
-*		      not use the optional registers.
-* 2.03a hvm  05/24/11 Updated the tcl to generate vector Ids for external
-*		      interrupts. CR565336
-* 2.04a bss  01/13/12 Added XIntc_ConnectFastHandler API for Fast Interrupt
-*		      and XIntc_SetNormalIntrMode for setting to normal
-*		      interrupt mode.
-* 2.04a asa  03/19/12 Changed the XIntc_Config struct. The order of entries
-*		      declared in the structure now matches with the
-*		      XIntc_ConfigTable generated by the driver tcl.
-* 2.05a bss  08/16/12 Updated to support relocatable vectors in Microblaze,
-*		      added IntVectorAddr to XIntc_Config for this.
-*		      Added XIntc_RegisterFastHandler API to register fast
-*		      interrupt handlers using base address.
-* 2.06a bss  01/28/13 To support Cascade mode:
-* 		      Added XIN_INTC_NOCASCADE,XIN_INTC_PRIMARY,
-*		      XIN_INTC_SECONDARY,XIN_INTC_LAST and
-*		      XIN_CONTROLLER_MAX_INTRS  macros
-*		      Added NumberofIntrs and IntcType fields in XIntc_Config
-*		      structure.
-*		      Modified XIntc_Initialize,XIntc_Start,XIntc_Connect
-*		      XIntc_Disconnect,XIntc_Enable,XIntc_Disable,
-*		      XIntc_Acknowledge,XIntc_ConnectFastHandler and
-*		      XIntc_SetNormalIntrMode APIs.Added XIntc_InitializeSlaves
-*		      API in xintc.c
-*  		      Modified XIntc_DeviceInterruptHandler,
-*  		      XIntc_SetIntrSvcOption,XIntc_RegisterHandler and
-*		      XIntc_RegisterFastHandler APIs.Added XIntc_CascadeHandler
-*		      API in xintc_l.c.
-*		      Modified XIntc_SetOptions API in xintc_options.c.
-*		      Modified XIntc_SimulateIntr API in xintc_selftest.c.
-*		      Modified driver tcl:
-*			to check for Cascade mode and generate XPAR_INTC_TYPE
-*			for each controller.
-*			Generate XPAR_INTC_MAX_NUM_INTR_INPUTS by adding all
-*			interrupt sources of all Controllers in Cascade mode.
-* 2.07a bss  10/18/13 To support Nested interrupts:
-*		      Modified XIntc_DeviceInterruptHandler API.
-*		      Added XIN_ILR_OFFSET macro in xintc_l.h.
-*		      Modified driver tcl to generate HAS_ILR parameter in
-*		      xparameters.h
-* 3.0   bss  01/28/13 Modified xintc.c to initialize IVAR register with
-*		      XPAR_MICROBLAZE_BASE_VECTORS + 0x10 to fix
-*		      CR#765931.
-*		      Modified driver tcl to generate XPAR_AXI_INTC_0_TYPE
-*		      correctly(CR#764865).
-*
-* @note
-*		For Cascade mode, Interrupt IDs are generated in xparameters.h
-*		as shown below:
-*
-*	    Master/Primary INTC
-*		 ______
-*		|      |-0      Secondary INTC
-*		|      |-.         ______
-*		|      |-.        |      |-32        Last INTC
-*		|      |-.        |      |-.          ______
-*		|______|<-31------|      |-.         |      |-64
-*			          |      |-.         |      |-.
-*			          |______|<-63-------|      |-.
-*                                                    |      |-.
-*                                                    |______|-95
-*
-*		All driver functions has to be called using DeviceId/
-*		InstancePtr/BaseAddress of Primary/Master Controller and
-*		Interrupts IDs generated in xparameters.h only.
-*		Driver functions takes care of Slave Controllers based on
-*		Interrupt ID passed. User must not use Interrupt source/ID
-*		31 of Primary and Secondary controllers to call driver
-*		functions.
-*
-*		For nested interrupts, XIntc_DeviceInterruptHandler saves
-*		microblaze r14 register on entry and restores on exit. This is
-*		required since compiler does not support nesting. It enables
-*		Microblaze interrupts after blocking further interrupts from
-*		the current interrupt number and interrupts below current
-*		interrupt proirity by writing to Interrupt Level Register of
-*		INTC on entry. On exit, it disables microblaze interrupts and
-*		restores ILR register default value(0xFFFFFFFF)back. It is
-*		recommended to increase STACK_SIZE in linker script for nested
-*		interrupts.
-* 3.0     adk    12/10/13  Updated as per the New Tcl API's
-* 3.0 	  adk 	 17/02/14  Fixed the CR:771287 Changes are made in the intc
-* 		           driver tcl.
-* 3.1     adk    8/4/14    Fixed the CR:783248 Changes are made in
-*			   the test-app tcl
-* 3.2     bss    4/8/14    Fixed driver tcl to handle external interrupt pins
-*			   correctly (CR#799609).
-* 3.3     adk    11/3/14   added generation of C_HAS_ILR parameter to
-*			   xparameters.h.Changes are made in the driver tcl file
-*			   (CR#828046).
-*
-* 
-* -******************************************************************************/ - -#ifndef XINTC_H /* prevent circular inclusions */ -#define XINTC_H /* by using protection macros */ - -#ifdef __cplusplus -extern "C" { -#endif - - -/***************************** Include Files *********************************/ - -#include "xil_types.h" -#include "xil_assert.h" -#include "xparameters.h" -#include "xstatus.h" -#include "xintc_l.h" - -/************************** Constant Definitions *****************************/ - -/** - * @name Configuration options - * These options are used in XIntc_SetOptions() to configure the device. - * @{ - */ -/** - *
- * XIN_SVC_SGL_ISR_OPTION	Service the highest priority pending interrupt
- *				and then return.
- * XIN_SVC_ALL_ISRS_OPTION	Service all of the pending interrupts and then
- *				return.
- * 
- */ -#define XIN_SVC_SGL_ISR_OPTION 1UL -#define XIN_SVC_ALL_ISRS_OPTION 2UL -/*@}*/ - -/** - * @name Start modes - * One of these values is passed to XIntc_Start() to start the device. - * @{ - */ -/** Simulation only mode, no hardware interrupts recognized */ -#define XIN_SIMULATION_MODE 0 -/** Real mode, no simulation allowed, hardware interrupts recognized */ -#define XIN_REAL_MODE 1 -/*@}*/ - -/** - * @name Masks to specify Interrupt Controller Mode - * @{ - */ -#define XIN_INTC_NOCASCADE 0 /* Normal - No Cascade Mode */ -#define XIN_INTC_PRIMARY 1 /* Master/Primary controller */ -#define XIN_INTC_SECONDARY 2 /* Secondary Slave Controllers */ -#define XIN_INTC_LAST 3 /* Last Slave Controller */ - -/*@}*/ - -/** - * @name Mask to specify maximum number of interrupt sources per controller - * @{ - */ -#define XIN_CONTROLLER_MAX_INTRS 32 /* Each Controller has 32 - interrupt pins */ -/*@}*/ - -/**************************** Type Definitions *******************************/ - -/** - * This typedef contains configuration information for the device. - */ -typedef struct { - u16 DeviceId; /**< Unique ID of device */ - u32 BaseAddress; /**< Register base address */ - u32 AckBeforeService; /**< Ack location per interrupt */ - int FastIntr; /**< Fast Interrupt enabled */ - u32 IntVectorAddr; /**< Interrupt Vector Address */ - int NumberofIntrs; /**< Number of Interrupt sources */ - u32 Options; /**< Device options */ - int IntcType; /**< Intc type 0 - No Cascade Mode - 1 - primary instance - 2 - secondary instance - 3 - last instance */ - -/** Static vector table of interrupt handlers */ -#if XPAR_INTC_0_INTC_TYPE != XIN_INTC_NOCASCADE - XIntc_VectorTableEntry HandlerTable[XIN_CONTROLLER_MAX_INTRS]; -#else - XIntc_VectorTableEntry HandlerTable[XPAR_INTC_MAX_NUM_INTR_INPUTS]; -#endif - -} XIntc_Config; - -/** - * The XIntc driver instance data. The user is required to allocate a - * variable of this type for every intc device in the system. A pointer - * to a variable of this type is then passed to the driver API functions. - */ -typedef struct { - u32 BaseAddress; /**< Base address of registers */ - u32 IsReady; /**< Device is initialized and ready */ - u32 IsStarted; /**< Device has been started */ - u32 UnhandledInterrupts; /**< Intc Statistics */ - XIntc_Config *CfgPtr; /**< Pointer to instance config entry */ - -} XIntc; - -/***************** Macros (Inline Functions) Definitions *********************/ - -/************************** Function Prototypes ******************************/ - -/* - * Required functions in xintc.c - */ -int XIntc_Initialize(XIntc * InstancePtr, u16 DeviceId); - -int XIntc_Start(XIntc * InstancePtr, u8 Mode); -void XIntc_Stop(XIntc * InstancePtr); - -int XIntc_Connect(XIntc * InstancePtr, u8 Id, - XInterruptHandler Handler, void *CallBackRef); -void XIntc_Disconnect(XIntc * InstancePtr, u8 Id); - -void XIntc_Enable(XIntc * InstancePtr, u8 Id); -void XIntc_Disable(XIntc * InstancePtr, u8 Id); - -void XIntc_Acknowledge(XIntc * InstancePtr, u8 Id); - -XIntc_Config *XIntc_LookupConfig(u16 DeviceId); - -int XIntc_ConnectFastHandler(XIntc *InstancePtr, u8 Id, - XFastInterruptHandler Handler); -void XIntc_SetNormalIntrMode(XIntc *InstancePtr, u8 Id); - -/* - * Interrupt functions in xintr_intr.c - */ -void XIntc_VoidInterruptHandler(void); -void XIntc_InterruptHandler(XIntc * InstancePtr); - -/* - * Options functions in xintc_options.c - */ -int XIntc_SetOptions(XIntc * InstancePtr, u32 Options); -u32 XIntc_GetOptions(XIntc * InstancePtr); - -/* - * Self-test functions in xintc_selftest.c - */ -int XIntc_SelfTest(XIntc * InstancePtr); -int XIntc_SimulateIntr(XIntc * InstancePtr, u8 Id); - -#ifdef __cplusplus -} -#endif - -#endif /* end of protection macro */ -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xintc_l.h b/thirdparty/libxil/include/xilinx/xintc_l.h deleted file mode 100644 index 9d9c9eaff..000000000 --- a/thirdparty/libxil/include/xilinx/xintc_l.h +++ /dev/null @@ -1,330 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xintc_l.h -* @addtogroup intc_v3_4 -* @{ -* -* This header file contains identifiers and low-level driver functions (or -* macros) that can be used to access the device. The user should refer to the -* hardware device specification for more details of the device operation. -* -* -* Note that users of the driver interface given in this file can register -* an interrupt handler dynamically (at run-time) using the -* XIntc_RegisterHandler() function. -* User of the driver interface given in xintc.h should still use -* XIntc_Connect(), as always. -* Also see the discussion of the interrupt vector tables in xintc.h. -* -* There are currently two interrupt handlers specified in this interface. -* -* - XIntc_LowLevelInterruptHandler() is a handler without any arguments that -* is used in cases where there is a single interrupt controller device in -* the system and the handler cannot be passed an argument. This function is -* provided mostly for backward compatibility. -* -* - XIntc_DeviceInterruptHandler() is a handler that takes a device ID as an -* argument, indicating which interrupt controller device in the system is -* causing the interrupt - thereby supporting multiple interrupt controllers. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who  Date     Changes
-* ----- ---- -------- -----------------------------------------------------
-* 1.00b jhl  04/24/02 First release
-* 1.00c rpm  10/17/03 New release. Support the static vector table created
-*                     in the xintc_g.c configuration table.
-* 1.10c mta  03/21/07 Updated to new coding style
-* 1.11a sv   11/21/07 Updated driver to support access through a DCR bridge
-* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs. _m is removed from all
-*		      the macro definitions.
-* 2.04a bss  01/13/12 Updated for adding defines for IMR and IVAR for
-*                     the FAST Interrupt
-* 2.05a bss  08/18/12 Added XIntc_RegisterFastHandler API to register fast
-*		      interrupt handlers using base address.
-* 2.07a bss  10/18/13 Added XIN_ILR_OFFSET macro for nested interrupts.
-*
-* 
-* -******************************************************************************/ - -#ifndef XINTC_L_H /* prevent circular inclusions */ -#define XINTC_L_H /* by using protection macros */ - -#ifdef __cplusplus -extern "C" { -#endif - -/***************************** Include Files *********************************/ - -#include "xil_types.h" -#include "xil_assert.h" -#include "xparameters.h" -#include "xil_io.h" - -/* - * XPAR_XINTC_USE_DCR_BRIDGE has to be set to 1 if the Intc device will be - * accessed through a DCR bus connected to a bridge. - */ -#define XPAR_XINTC_USE_DCR_BRIDGE 0 - -#if ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) -#include "xio_dcr.h" -#endif - -/************************** Constant Definitions *****************************/ - -/* define the offsets from the base address for all the registers of the - * interrupt controller, some registers may be optional in the hardware device - */ -#if ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) - -#define XIN_ISR_OFFSET 0 /* Interrupt Status Register */ -#define XIN_IPR_OFFSET 1 /* Interrupt Pending Register */ -#define XIN_IER_OFFSET 2 /* Interrupt Enable Register */ -#define XIN_IAR_OFFSET 3 /* Interrupt Acknowledge Register */ -#define XIN_SIE_OFFSET 4 /* Set Interrupt Enable Register */ -#define XIN_CIE_OFFSET 5 /* Clear Interrupt Enable Register */ -#define XIN_IVR_OFFSET 6 /* Interrupt Vector Register */ -#define XIN_MER_OFFSET 7 /* Master Enable Register */ -#define XIN_IMR_OFFSET 8 /* Interrupt Mode Register , this is present - * only for Fast Interrupt */ -#define XIN_IVAR_OFFSET 64 /* Interrupt Vector Address Register - * Interrupt 0 Offest, this is present - * only for Fast Interrupt */ - -#else /* ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) */ - -#define XIN_ISR_OFFSET 0 /* Interrupt Status Register */ -#define XIN_IPR_OFFSET 4 /* Interrupt Pending Register */ -#define XIN_IER_OFFSET 8 /* Interrupt Enable Register */ -#define XIN_IAR_OFFSET 12 /* Interrupt Acknowledge Register */ -#define XIN_SIE_OFFSET 16 /* Set Interrupt Enable Register */ -#define XIN_CIE_OFFSET 20 /* Clear Interrupt Enable Register */ -#define XIN_IVR_OFFSET 24 /* Interrupt Vector Register */ -#define XIN_MER_OFFSET 28 /* Master Enable Register */ -#define XIN_IMR_OFFSET 32 /* Interrupt Mode Register , this is present - * only for Fast Interrupt */ -#define XIN_ILR_OFFSET 36 /* Interrupt level register */ -#define XIN_IVAR_OFFSET 0x100 /* Interrupt Vector Address Register - * Interrupt 0 Offest, this is present - * only for Fast Interrupt */ - - - -#endif /* ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) */ - -/* Bit definitions for the bits of the MER register */ - -#define XIN_INT_MASTER_ENABLE_MASK 0x1UL -#define XIN_INT_HARDWARE_ENABLE_MASK 0x2UL /* once set cannot be cleared */ - -/**************************** Type Definitions *******************************/ - -/* The following data type defines each entry in an interrupt vector table. - * The callback reference is the base address of the interrupting device - * for the driver interface given in this file and an instance pointer for the - * driver interface given in xintc.h file. - */ -typedef struct { - XInterruptHandler Handler; - void *CallBackRef; -} XIntc_VectorTableEntry; - -typedef void (*XFastInterruptHandler) (void); - -/***************** Macros (Inline Functions) Definitions *********************/ - -/* - * Define the appropriate I/O access method to memory mapped I/O or DCR. - */ -#if ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) - -#define XIntc_In32 XIo_DcrIn -#define XIntc_Out32 XIo_DcrOut - -#else - -#define XIntc_In32 Xil_In32 -#define XIntc_Out32 Xil_Out32 - -#endif - -/****************************************************************************/ -/** -* -* Enable all interrupts in the Master Enable register of the interrupt -* controller. The interrupt controller defaults to all interrupts disabled -* from reset such that this macro must be used to enable interrupts. -* -* @param BaseAddress is the base address of the device. -* -* @return None. -* -* @note C-style signature: -* void XIntc_MasterEnable(u32 BaseAddress); -* -*****************************************************************************/ -#define XIntc_MasterEnable(BaseAddress) \ - XIntc_Out32((BaseAddress) + XIN_MER_OFFSET, \ - XIN_INT_MASTER_ENABLE_MASK | XIN_INT_HARDWARE_ENABLE_MASK) - -/****************************************************************************/ -/** -* -* Disable all interrupts in the Master Enable register of the interrupt -* controller. -* -* @param BaseAddress is the base address of the device. -* -* @return None. -* -* @note C-style signature: -* void XIntc_MasterDisable(u32 BaseAddress); -* -*****************************************************************************/ -#define XIntc_MasterDisable(BaseAddress) \ - XIntc_Out32((BaseAddress) + XIN_MER_OFFSET, 0) - -/****************************************************************************/ -/** -* -* Enable specific interrupt(s) in the interrupt controller. -* -* @param BaseAddress is the base address of the device -* @param EnableMask is the 32-bit value to write to the enable register. -* Each bit of the mask corresponds to an interrupt input signal -* that is connected to the interrupt controller (INT0 = LSB). -* Only the bits which are set in the mask will enable interrupts. -* -* @return None. -* -* @note C-style signature: -* void XIntc_EnableIntr(u32 BaseAddress, u32 EnableMask); -* -*****************************************************************************/ -#define XIntc_EnableIntr(BaseAddress, EnableMask) \ - XIntc_Out32((BaseAddress) + XIN_IER_OFFSET, (EnableMask)) - -/****************************************************************************/ -/** -* -* Disable specific interrupt(s) in the interrupt controller. -* -* @param BaseAddress is the base address of the device -* @param DisableMask is the 32-bit value to write to the enable register. -* Each bit of the mask corresponds to an interrupt input signal -* that is connected to the interrupt controller (INT0 = LSB). -* Only the bits which are set in the mask will disable interrupts. -* -* @return None. -* -* @note C-style signature: -* void XIntc_DisableIntr(u32 BaseAddress, u32 DisableMask); -* -*****************************************************************************/ -#define XIntc_DisableIntr(BaseAddress, DisableMask) \ - XIntc_Out32((BaseAddress) + XIN_IER_OFFSET, ~(DisableMask)) - -/****************************************************************************/ -/** -* -* Acknowledge specific interrupt(s) in the interrupt controller. -* -* @param BaseAddress is the base address of the device -* @param AckMask is the 32-bit value to write to the acknowledge -* register. Each bit of the mask corresponds to an interrupt input -* signal that is connected to the interrupt controller (INT0 = -* LSB). Only the bits which are set in the mask will acknowledge -* interrupts. -* -* @return None. -* -* @note C-style signature: -* void XIntc_AckIntr(u32 BaseAddress, u32 AckMask); -* -*****************************************************************************/ -#define XIntc_AckIntr(BaseAddress, AckMask) \ - XIntc_Out32((BaseAddress) + XIN_IAR_OFFSET, (AckMask)) - -/****************************************************************************/ -/** -* -* Get the interrupt status from the interrupt controller which indicates -* which interrupts are active and enabled. -* -* @param BaseAddress is the base address of the device -* -* @return The 32-bit contents of the interrupt status register. Each bit -* corresponds to an interrupt input signal that is connected to -* the interrupt controller (INT0 = LSB). Bits which are set -* indicate an active interrupt which is also enabled. -* -* @note C-style signature: -* u32 XIntc_GetIntrStatus(u32 BaseAddress); -* -*****************************************************************************/ -#define XIntc_GetIntrStatus(BaseAddress) \ - (XIntc_In32((BaseAddress) + XIN_ISR_OFFSET) & \ - XIntc_In32((BaseAddress) + XIN_IER_OFFSET)) - -/************************** Function Prototypes ******************************/ - -/* - * Interrupt controller handlers, to be connected to processor exception - * handling code. - */ -void XIntc_LowLevelInterruptHandler(void); -void XIntc_DeviceInterruptHandler(void *DeviceId); - -/* Various configuration functions */ -void XIntc_SetIntrSvcOption(u32 BaseAddress, int Option); - -void XIntc_RegisterHandler(u32 BaseAddress, int InterruptId, - XInterruptHandler Handler, void *CallBackRef); - -void XIntc_RegisterFastHandler(u32 BaseAddress, u8 Id, - XFastInterruptHandler FastHandler); - -/************************** Variable Definitions *****************************/ - - -#ifdef __cplusplus -} -#endif - -#endif /* end of protection macro */ -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xllfifo.h b/thirdparty/libxil/include/xilinx/xllfifo.h deleted file mode 100644 index e9b59d77c..000000000 --- a/thirdparty/libxil/include/xilinx/xllfifo.h +++ /dev/null @@ -1,715 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2005 - 2014 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** - * - * @file xllfifo.h -* @addtogroup llfifo_v5_0 -* @{ -* @details - * - * The Xilinx Dual Channel Fifo driver component. This driver supports the - * Virtex-5(TM) and Virtex-4(TM) XPS_ll_Fifo and the AxiFifo. - * - * For a full description of the bridge features, please see the HW spec. This - * driver supports the following features: - * - Memory mapped access to host interface registers - * - API for polled frame transfers - * - API for interrupt driven frame transfers - * - Virtual memory support - * - Full duplex operation - * - *

Driver Description

- * - * This driver enables higher layer software to access the XPS_llFifo core - * using any alignment in the data buffers. - * - * This driver supports send and receive channels in the same instance - * structure in the same fashion as the hardware core. - * - *

Initialization

- * - * An instance of this driver is initialized using a call to Initialize(). - * - *

Usage

- * - * It is fairly simple to use the API provided by this FIFO driver. The - * only somewhat tricky part is that the calling code must correctly call - * a couple routines in the right sequence for receive and transmit. - * - * This sequence is described here. Check the routine functional - * descriptions for information on how to use a specific API routine. - * - *

Receive

- * - * A frame is received by using the following sequence:
- * 1) call XLlFifo_RxOccupancy() to check the occupancy count
- * 2) call XLlFifo_RxGetLen() to get the length of the next incoming frame
- * 3) call XLlFifo_Read() one or more times to read the number of bytes - * reported by XLlFifo_RxGetLen().
- * - * For example: - *
- * 	while (XLlFifo_RxOccupancy(&RxInstance)) {
- * 		frame_len = XLlFifo_RxGetLen(&RxInstance);
- *		while (frame_len) {
- * 			unsigned bytes = min(sizeof(buffer), frame_len);
- * 			XLlFifo_Read(&RxInstance, buffer, bytes);
- * 			// ********
- * 			// do something with buffer here
- * 			// ********
- * 			frame_len -= bytes;
- *		}
- * 	}
- * 
- * - * This FIFO hardware core does not support a sequence where the - * calling code calls RxGetLen() twice in a row and then receive the data - * for two frames. Each frame must be read in by calling RxGetLen() just - * prior to reading the data. - * - *

Transmit

- * A frame is transmittted by using the following sequence:
- * 1) call XLlFifo_Write() one or more times to write all the of bytes in - * the next frame.
- * 2) call XLlFifo_TxSetLen() to begin the transmission of frame just - * written.
- * - * For example: - *
- * 	frame_left = frame_len;
- * 	while (frame_left) {
- * 		unsigned bytes = min(sizeof(buffer), frame_left);
- * 		XLlFifo_Write(&TxInstance, buffer, bytes);
- * 		// ********
- * 		// do something here to refill buffer
- * 		// ********
- * 		frame_left -= bytes;
- * 	}
- * 	XLlFifo_TxSetLen(&RxInstance, frame_len);
- * 
- * - * This FIFO hardware core does not support a sequence where the - * calling code writes the data for two frames and then calls TxSetLen() - * twice in a row. Each frame must be written by writting the data for one - * frame and then calling TxSetLen(). - * - *

Interrupts

- * This driver does not handle interrupts from the FIFO hardware. The - * software layer above may make use of the interrupts by setting up its - * own handlers for the interrupts. - * - *
- * MODIFICATION HISTORY:
- *
- * Ver   Who  Date     Changes
- * ----- ---- -------- -------------------------------------------------------
- * 1.00a jvb  10/12/06 First release
- * 1.01a sdm  08/22/08 Removed support for static interrupt handlers from the
- *		       MDD file
- * 1.02a jz   12/04/09 Hal phase 1 support
- * 2.01a asa  09/17/10 Added code for resetting Local Link/AXI Streaming
- *		       interface for CR574868
- * 2.02a asa  12/27/11 Changed the function XStrm_Read in xtreamer.c to reset
- *		       HeadIndex to zero when all bytes have been read.
- *		       Changed the macro XStrm_IsRxInternalEmpty in file
- *		       xtreamer.h to use FrmByteCnt instead of HeadIndex.
- *		       When FrmByteCnt is zero, this means all internal buffers
- *		       in streamer are empty. Earlier implementation using
- *		       HeadIndex was not very clear and could give improper
- *		       results for some cases.
- *		       Changed the macro XLlFifo_IsRxEmpty in file xllfifo.h
- *		       These changes are done to fix the CR 604650.
-  * 2.03a asa  14/08/12  Added XLLF_TDR_OFFSET, XLLF_RDR_OFFSET
- *		         defines for the new registers, and XLLF_INT_TFPF_MASK,
- *		         XLLF_INT_TFPE_MASK, XLLF_INT_RFPF_MASK and
- *		         XLLF_INT_RFPE_MASK for the new version of the
- *		         AXI4-Stream FIFO core (v2.01a and later)
- *
- * 3.00a adk 08/10/13 Added support for AXI4 Datainterface.Changes are
- * 		      In Xllfifo.c file XLlFifo_RxGetWord,XLlFifo_TxPutword.
- * 		      In XLlfifo.h file updated XLlfifo structure for
- * 		      Axi4BaseAddress and for Datainterface type provided
- *		      polling and interrupt examples. XLlfifo_IsRxDone Macro
- *		      Is added in the XLlfifo.h file for polledmode exmaple.
- *		      Added Static initialzation for the driver.
- *		      XLlFifo_Initialize is still used to make the driver
- *		      backward compatible.
- * 4.0   adk  19/12/13 Updated as per the New Tcl API's
- * 5.0   adk  15/05/15 Updated the register offsets in the AXI4 data path
- *		       as per latest IP version(v4.1)(CR:860254).
- *
- * 
- * - *****************************************************************************/ -#ifndef XLLFIFO_H /* prevent circular inclusions */ -#define XLLFIFO_H /* by using preprocessor symbols */ - -/* force C linkage */ -#ifdef __cplusplus -extern "C" { -#endif - -/***************************** Include Files *********************************/ - -/* This order needs to be kept this way to avoid xstatus/xil_types conflict */ -#include "xstreamer.h" -#include "xllfifo_hw.h" - -/**************************** Type Definitions *******************************/ - -/** - * This typedef defines a run-time instance of an XLlFifo device. - */ -typedef struct XLlFifo { - u32 BaseAddress; /**< BaseAddress is the physical base address of the - * device's registers - */ - - u32 IsReady; /**< IsReady is non-zero if the driver instance - * has been initialized. - */ - - u32 Axi4BaseAddress; /**< BaseAddress if the FIFO Data interface is - * AXI4 this address should use for FIFO - * access - */ - u32 Datainterface; /**< Data interface of the FIFO. This value is zero - * if the Datainterface is AXI4-lite. - */ - XStrm_RxFifoStreamer RxStreamer; /**< RxStreamer is the byte streamer - * instance for the receive channel. - */ - XStrm_TxFifoStreamer TxStreamer; /**< TxStreamer is the byte streamer - * instance for the transmit channel. - */ -} XLlFifo; - -typedef struct XLlFifo_Config { - u32 DeviceId; /**< Deviceid of the AXI FIFO */ - u32 BaseAddress; /**< Base Address of the AXI FIFO */ - u32 Axi4BaseAddress; /**< Axi4 interface Base address */ - u32 Datainterface; /**< Type of Datainterface */ -}XLlFifo_Config; - -/****************************************************************************/ -/** -* -* XLlFifo_Reset resets both the Tx and Rx channels and the local link interface -* the FIFO specified by InstancePtr. XLlFifo_TxReset resets also sends a -* reset pulse to the downstream device (e.g. TEMAC). XLlFifo_Reset drops any -* bytes in the FIFO not yet retrieved. XLlFifo_Reset drops any bytes in the FIFO -* not yet transmitted. -* -* @param InstancePtr references the FIFO on which to operate. -* -* @return N/A -* -* @note -* C-style signature: -* void XLlFifo_Reset(XLlFifo *InstancePtr) -* -*****************************************************************************/ -#define XLlFifo_Reset(InstancePtr) \ - XLlFifo_WriteReg((InstancePtr)->BaseAddress, XLLF_LLR_OFFSET, \ - XLLF_LLR_RESET_MASK) - - -/****************************************************************************/ -/** -* -* XLlFifo_Status returns a bit mask of the interrupt status register (ISR) -* for the FIFO specified by InstancePtr. XLlFifo_Status can be used -* to query the status of the FIFO without having to have interrupts enabled. -* -* @param InstancePtr references the FIFO on which to operate. -* -* @return XLlFifo_IntStatus returns a bit mask of the status conditions. -* The mask will be a set of bitwise or'd values from the -* XLLF_INT_*_MASK preprocessor symbols. -* -* @note -* C-style signature: -* u32 XLlFifo_IntStatus(XLlFifo *InstancePtr) -* -*****************************************************************************/ -#define XLlFifo_Status(InstancePtr) \ - XLlFifo_ReadReg((InstancePtr)->BaseAddress, XLLF_ISR_OFFSET) - -/****************************************************************************/ -/** -* -* XLlFifo_IntEnable enables the interrupts specified in Mask for the -* FIFO specified by InstancePtr. The corresponding interrupt for each bit -* set to 1 in Mask, will be enabled. -* -* @param InstancePtr references the FIFO on which to operate. -* -* @param Mask contains a bit mask of the interrupts to enable. The mask -* can be formed using a set of bitwise or'd values from the -* XLLF_INT_*_MASK preprocessor symbols. -* -* @return N/A -* -* @note -* C-style signature: -* void XLlFifo_IntEnable(XLlFifo *InstancePtr, u32 Mask) -* -*****************************************************************************/ -#define XLlFifo_IntEnable(InstancePtr, Mask) \ -{ \ - u32 Reg = XLlFifo_ReadReg((InstancePtr)->BaseAddress, \ - XLLF_IER_OFFSET); \ - Reg |= ((Mask) & XLLF_INT_ALL_MASK); \ - XLlFifo_WriteReg((InstancePtr)->BaseAddress, XLLF_IER_OFFSET, \ - Reg); \ -} - -/****************************************************************************/ -/** -* -* XLlFifo_IntDisable disables the interrupts specified in Mask for the -* FIFO specified by InstancePtr. The corresponding interrupt for each bit -* set to 1 in Mask, will be disabled. In other words, XLlFifo_IntDisable -* uses the "set a bit to clear it" scheme. -* -* @param InstancePtr references the FIFO on which to operate. -* -* @param Mask contains a bit mask of the interrupts to disable. The mask -* can be formed using a set of bitwise or'd values from the -* XLLF_INT_*_MASK preprocessor symbols. -* -* @return N/A -* -* @note -* C-style signature: -* void XLlFifo_IntDisable(XLlFifo *InstancePtr, u32 Mask) -* -*****************************************************************************/ -#define XLlFifo_IntDisable(InstancePtr, Mask) \ -{ \ - u32 Reg = XLlFifo_ReadReg((InstancePtr)->BaseAddress, \ - XLLF_IER_OFFSET); \ - Reg &= ~((Mask) & XLLF_INT_ALL_MASK); \ - XLlFifo_WriteReg((InstancePtr)->BaseAddress, XLLF_IER_OFFSET, \ - Reg); \ -} - -/****************************************************************************/ -/** -* -* XLlFifo_IntPending returns a bit mask of the pending interrupts for the -* FIFO specified by InstancePtr. Each bit set to 1 in the return value -* represents a pending interrupt. -* -* @param InstancePtr references the FIFO on which to operate. -* -* @return XLlFifo_IntPending returns a bit mask of the interrupts that are -* pending. The mask will be a set of bitwise or'd values from the -* XLLF_INT_*_MASK preprocessor symbols. -* -* @note -* C-style signature: -* u32 XLlFifo_IntPending(XLlFifo *InstancePtr) -* -*****************************************************************************/ -#ifdef DEBUG -extern u32 _xllfifo_ipie_value; -extern u32 _xllfifo_ipis_value; -#define XLlFifo_IntPending(InstancePtr) \ - (_xllfifo_ipie_value = XLlFifo_ReadReg( \ - (InstancePtr)->BaseAddress, XLLF_IER_OFFSET), \ - _xllfifo_ipis_value = XLlFifo_ReadReg( \ - (InstancePtr)->BaseAddress, XLLF_ISR_OFFSET), \ - (_xllfifo_ipie_value & _xllfifo_ipis_value)) -#else -#define XLlFifo_IntPending(InstancePtr) \ - (XLlFifo_ReadReg((InstancePtr)->BaseAddress, XLLF_IER_OFFSET) & \ - XLlFifo_ReadReg((InstancePtr)->BaseAddress, XLLF_ISR_OFFSET)) -#endif - -/****************************************************************************/ -/** -* -* XLlFifo_IntClear clears pending interrupts specified in Mask for the -* FIFO specified by InstancePtr. The corresponding pending interrupt for -* each bit set to 1 in Mask, will be cleared. In other words, -* XLlFifo_IntClear uses the "set a bit to clear it" scheme. -* -* @param InstancePtr references the FIFO on which to operate. -* -* @param Mask contains a bit mask of the pending interrupts to clear. The -* mask can be formed using a set of bitwise or'd values from the -* XLLF_INT_*_MASK preprocessor symbols. -* -* @note -* C-style signature: -* void XLlFifo_IntClear(XLlFifo *InstancePtr, u32 Mask) -* -*****************************************************************************/ -#define XLlFifo_IntClear(InstancePtr, Mask) \ - XLlFifo_WriteReg((InstancePtr)->BaseAddress, XLLF_ISR_OFFSET, \ - ((Mask) & XLLF_INT_ALL_MASK)) - -/****************************************************************************/ -/** -* -* XLlFifo_RxReset resets the receive channel of the FIFO specified by -* InstancePtr. XLlFifo_RxReset drops any bytes in the FIFO not yet -* retrieved. -* -* The calling software may want to test for the completion of the reset by -* reading the interrupt status (IS) register and testing for the Rx Reset -* complete (RRC) bit. -* -* @param InstancePtr references the FIFO on which to operate. -* -* @return N/A -* -* @note -* C-style signature: -* void XLlFifo_RxReset(XLlFifo *InstancePtr) -* -*****************************************************************************/ -#define XLlFifo_RxReset(InstancePtr) \ - XLlFifo_WriteReg((InstancePtr)->BaseAddress, XLLF_RDFR_OFFSET, \ - XLLF_RDFR_RESET_MASK) - -/****************************************************************************/ -/** -* -* XLlFifo_IsRxEmpty returns true if the receive channel of the FIFO, specified -* by InstancePtr, is empty. -* -* @param InstancePtr references the FIFO on which to operate. -* -* @return XLlFifo_IsRxEmpty returns TRUE when the receive channel of the -* FIFO is empty. Otherwise, XLlFifo_IsRxEmpty returns FALSE. -* -* @note -* C-style signature: -* int XLlFifo_IsRxEmpty(XLlFifo *InstancePtr) -* -*****************************************************************************/ -#define XLlFifo_IsRxEmpty(InstancePtr) \ - ((XLlFifo_ReadReg((InstancePtr)->BaseAddress, XLLF_RDFO_OFFSET) == 0) \ - ? TRUE : FALSE) - - -/*****************************************************************************/ -/** -* -* XLlFifo_RxOccupancy returns the number of 32-bit words available (occupancy) to -* be read from the receive channel of the FIFO, specified by InstancePtr. -* -* The xps_ll_fifo core uses the same fifo to store data values and frame length -* values. Upon initialization, the XLlFifo_RxOccupancy will give the value of -* 1, which means one length value (a reserved fifo location) and no data -* values. -* -* @param InstancePtr references the FIFO on which to operate. -* -* @return XLlFifo_RxOccupancy returns the occupancy count for the specified -* packet FIFO. -* -* @note -* -* C Signature: u32 XLlFifo_RxOccupancy(XLlFifo *InstancePtr) -* -******************************************************************************/ -#define XLlFifo_RxOccupancy(InstancePtr) \ - XStrm_RxOccupancy(&((InstancePtr)->RxStreamer)) - -/*****************************************************************************/ -/** -* -* XLlFifo_RxGetLen notifies the hardware that the program is ready to receive -* the next frame from the receive channel of the FIFO, specified by -* InstancePtr. -* -* Note that the program must first call XLlFifo_RxGetLen before pulling data -* out of the receive channel of the FIFO with XLlFifo_Read. -* -* @param InstancePtr references the FIFO on which to operate. -* -* @return XLlFifo_RxGetLen returns the number of bytes available in the next -* frame. -* -* @note -* -* C Signature: u32 XLlFifo_RxGetLen(XLlFifo *InstancePtr) -* -******************************************************************************/ -#define XLlFifo_RxGetLen(InstancePtr) \ - XStrm_RxGetLen(&((InstancePtr)->RxStreamer)) - -/*****************************************************************************/ -/** -* -* XLlFifo_Read reads Bytes bytes from the receive channel of the FIFO -* referenced by InstancePtr to the block of memory, referenced by -* BufPtr. -* -* Care must be taken to ensure that the number of bytes read with one or more -* calls to XLlFifo_Read() does not exceed the number of bytes available given -* from the last call to XLlFifo_RxGetLen(). -* -* @param InstancePtr references the FIFO on which to operate. -* -* @param BufPtr specifies the memory address to place the data read. -* -* @param Bytes specifies the number of bytes to read. -* -* @return N/A -* -* @note -* Error handling is handled through hardware exceptions and interrupts. -* -* C Signature: void XLlFifo_Read(XLlFifo *InstancePtr, void *BufPtr, unsigned Bytes) -* -******************************************************************************/ -#define XLlFifo_Read(InstancePtr, BufPtr, Bytes) \ - XStrm_Read(&((InstancePtr)->RxStreamer), (BufPtr), (Bytes)) - -/****************************************************************************/ -/** -* -* XLlFifo_TxReset resets the transmit channel of the FIFO specified by -* InstancePtr. XLlFifo_TxReset drops any bytes in the FIFO not yet -* transmitted. -* -* The calling software may want to test for the completion of the reset by -* reading the interrupt status (IS) register and testing for the Tx Reset -* complete (TRC) bit. -* -* @param InstancePtr references the FIFO on which to operate. -* -* @return N/A -* -* @note -* C-style signature: -* void XLlFifo_TxReset(XLlFifo *InstancePtr) -* -*****************************************************************************/ -#define XLlFifo_TxReset(InstancePtr) \ - XLlFifo_WriteReg((InstancePtr)->BaseAddress, XLLF_TDFR_OFFSET, \ - XLLF_TDFR_RESET_MASK) - -/****************************************************************************/ -/** -* -* XLlFifo_IsTxDone returns true if the transmission in the transmit channel -* of the FIFO, specified by InstancePtr, is complete. XLlFifo_IsTxDone -* works only if the TC bit in the IS register is cleared before sending a -* frame. -* -* @param InstancePtr references the FIFO on which to operate. -* -* @return XLlFifo_IsTxDone returns TRUE when the transmit channel of the -* FIFO is complete. Otherwise, XLlFifo_IsTxDone returns FALSE. -* -* @note -* C-style signature: -* int XLlFifo_IsTxDone(XLlFifo *InstancePtr) -* -*****************************************************************************/ -#define XLlFifo_IsTxDone(InstancePtr) \ - ((XLlFifo_ReadReg((InstancePtr)->BaseAddress, XLLF_ISR_OFFSET) & \ - XLLF_INT_TC_MASK) \ - ? TRUE : FALSE) - -/****************************************************************************/ -/** -* -* XLlFifo_IsRxDone returns true if the reception in the receive channel -* of the FIFO, specified by InstancePtr, is complete. XLlFifo_IsRxDone -* works only if the RC bit in the ISR register is cleared before receiving a -* frame. -* -* @param InstancePtr references the FIFO on which to operate. -* -* @return XLlFifo_IsRxDone returns TRUE when the receive channel of the -* FIFO is complete. Otherwise, XLlFifo_IsRxDone returns FALSE. -* -* @note -* C-style signature: -* int XLlFifo_IsRxDone(XLlFifo *InstancePtr) -* -*****************************************************************************/ -#define XLlFifo_IsRxDone(InstancePtr) \ - ((XLlFifo_ReadReg((InstancePtr)->BaseAddress, XLLF_ISR_OFFSET) & \ - XLLF_INT_RC_MASK) \ - ? TRUE : FALSE) - -/****************************************************************************/ -/** -* -* XLlFifo_TxVacancy returns the number of unused 32 bit words available -* (vacancy) in the send channel of the FIFO specified by InstancePtr. -* -* The xps_ll_fifo core uses the same fifo to store data values and frame length -* values. Upon initialization, the XLlFifo_TxVacancy will give the value of -* FIFO_WIDTH - 1, which means one length value used (a reserved fifo location) -* and no data values yet present. -* -* @param InstancePtr references the FIFO on which to operate. -* -* @return XLlFifo_TxVacancy returns the vacancy count in 32-bit words for -* the specified FIFO. -* -* @note -* C-style signature: -* u32 XLlFifo_TxVacancy(XLlFifo *InstancePtr) -* -*****************************************************************************/ -#define XLlFifo_TxVacancy(InstancePtr) \ - XStrm_TxVacancy(&((InstancePtr)->TxStreamer)) - -/*****************************************************************************/ -/** -* -* XLlFifo_TxSetLen begins a hardware transfer of Bytes bytes out of the -* transmit channel of the FIFO specified by InstancePtr. -* -* @param InstancePtr references the FIFO on which to operate. -* -* @param Bytes specifies the frame length in bytes. -* -* @return N/A -* -* @note -* -* C Signature: void XLlFifo_TxSetLen(XLlFifo *InstancePtr, u32 Bytes) -* -******************************************************************************/ -#define XLlFifo_TxSetLen(InstancePtr, Bytes) \ - XStrm_TxSetLen(&((InstancePtr)->TxStreamer), (Bytes)) - -/*****************************************************************************/ -/** -* -* XLlFifo_Write writes Bytes bytes of the block of memory, referenced by -* BufPtr, to the transmit channel of the FIFO referenced by -* InstancePtr. -* -* Care must be taken to ensure that the number of bytes written with one or -* more calls to XLlFifo_Write() matches the number of bytes given in the next -* call to XLlFifo_TxSetLen(). -* -* @param InstancePtr references the FIFO on which to operate. -* -* @param BufPtr specifies the memory address of data to write. -* -* @param Bytes specifies the number of bytes to write. -* -* @return N/A -* -* @note -* Error handling is handled through hardware exceptions and interrupts. -* -* C Signature: void XLlFifo_Write(XLlFifo *InstancePtr, void *BufPtr, unsigned Bytes) -* -******************************************************************************/ -#define XLlFifo_Write(InstancePtr, BufPtr, Bytes) \ - XStrm_Write(&((InstancePtr)->TxStreamer), (BufPtr), (Bytes)) - - -/*****************************************************************************/ -/** -* -* XLlFifo_WriteTdr writes to the Transmit Destination Register (TDR) -* -* The TDR stores the destination address corresponding to the packet to be -* transmitted. When presenting a transmit packet to the AXI4-Stream FIFO core -* the following sequence should be followed -* - Write the destination address into TDR first, -* - Write the packet data to the Transmit Data FIFO next -* - Write the length of the packet into the Transmit Length Register. -* -* @param InstancePtr references the FIFO on which to operate. -* @param Tdest is the Transmit Destination address to be written to TDR. -* -* @return N/A -* -* @note C Signature: -* void XLlFifo_WriteTdr(XLlFifo *InstancePtr, u32 Tdest); -* -******************************************************************************/ -#define XLlFifo_WriteTdr(InstancePtr, Tdest) \ - XLlFifo_WriteReg((InstancePtr)->BaseAddress, XLLF_TDR_OFFSET, \ - Tdest & 0xF) - -/*****************************************************************************/ -/** -* -* XLlFifo_ReadTdr returns the contents of the Receive Destination Register(RDR). -* -* The RDR contains destination address corresponding to the valid packet that -* is received. The RDR should only be read when a receive packet is available -* for processing (the receive occupancy is not zero). -* Once the RDR is read, the receive packet data should be read from the receive -* data FIFO before the RDR is read again. The RDR values are stored in the -* receive data FIFO by the AXI4-Stream FIFO core with the data of each packet. -* The RDR value for the subsequent packet to be processed is moved to the RDR -* when the previous RDR value has been read. -* -* @param InstancePtr references the FIFO on which to operate. -* -* @return The Receive Destination address read from the RDR. -* -* @note C Signature: -* u32 XLlFifo_ReadRdr(XLlFifo *InstancePtr) -* -******************************************************************************/ -#define XLlFifo_ReadRdr(InstancePtr) \ - XLlFifo_ReadReg((InstancePtr)->BaseAddress, XLLF_RDR_OFFSET) - -/************************** Function Prototypes ******************************/ -/* - * Initialization functions xllfifo.c - */ -int XLlFifo_CfgInitialize(XLlFifo *InstancePtr, - XLlFifo_Config *Config, u32 EffectiveAddress); -void XLlFifo_Initialize(XLlFifo *InstancePtr, u32 BaseAddress); -XLlFifo_Config *XLlFfio_LookupConfig(u32 DeviceId); -u32 XLlFifo_iRxOccupancy(XLlFifo *InstancePtr); -u32 XLlFifo_iRxGetLen(XLlFifo *InstancePtr); -u32 XLlFifo_iTxVacancy(XLlFifo *InstancePtr); -void XLlFifo_iTxSetLen(XLlFifo *InstancePtr, u32 Bytes); -u32 XLlFifo_RxGetWord(XLlFifo *InstancePtr); -void XLlFifo_TxPutWord(XLlFifo *InstancePtr, u32 Word); - -#ifdef __cplusplus -} -#endif -#endif /* XLLFIFO_H end of preprocessor protection symbols */ -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xllfifo_hw.h b/thirdparty/libxil/include/xilinx/xllfifo_hw.h deleted file mode 100644 index 694dd358e..000000000 --- a/thirdparty/libxil/include/xilinx/xllfifo_hw.h +++ /dev/null @@ -1,242 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2005 - 2014 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xllfifo_hw.h -* @addtogroup llfifo_v5_0 -* @{ -* -* This header file contains identifiers and low-level driver functions (or -* macros) that can be used to access the xps_ll_fifo core. -* High-level driver functions are defined in xpfifo.h. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who  Date     Changes
-* ----- ---- -------- -------------------------------------------------------
-* 1.00a jvb  10/16/06 First release.
-* 1.02a jz   12/04/09  Hal phase 1 support
-* 2.00a hbm  01/20/10  Hal phase 1 support, bump up major release
-* 2.03a asa  14/08/12  Added XLLF_TDR_OFFSET, XLLF_RDR_OFFSET
-*		       defines for the new registers, and XLLF_INT_TFPF_MASK,
-*		       XLLF_INT_TFPE_MASK, XLLF_INT_RFPF_MASK and
-*		       XLLF_INT_RFPE_MASK for the new version of the
-*		       AXI4-Stream FIFO core (v2.01a and later)
-* 
-* -******************************************************************************/ - -#ifndef XLLFIFO_HW_H /* prevent circular inclusions */ -#define XLLFIFO_HW_H /* by using protection macros */ - -#ifdef __cplusplus -extern "C" { -#endif - -/***************************** Include Files *********************************/ - -#include "xdebug.h" -#include "xil_io.h" -#include "xil_types.h" - -/************************** Constant Definitions *****************************/ - -/* Register offset definitions. Unless otherwise noted, register access is - * 32 bit. - */ - -/** @name Registers - * @{ - */ -#define XLLF_ISR_OFFSET 0x00000000 /**< Interrupt Status */ -#define XLLF_IER_OFFSET 0x00000004 /**< Interrupt Enable */ - -#define XLLF_TDFR_OFFSET 0x00000008 /**< Transmit Reset */ -#define XLLF_TDFV_OFFSET 0x0000000c /**< Transmit Vacancy */ -#define XLLF_TDFD_OFFSET 0x00000010 /**< Transmit Data */ -#define XLLF_AXI4_TDFD_OFFSET 0x00000000 /**< Axi4 Transmit Data */ -#define XLLF_TLF_OFFSET 0x00000014 /**< Transmit Length */ - -#define XLLF_RDFR_OFFSET 0x00000018 /**< Receive Reset */ -#define XLLF_RDFO_OFFSET 0x0000001c /**< Receive Occupancy */ -#define XLLF_RDFD_OFFSET 0x00000020 /**< Receive Data */ -#define XLLF_AXI4_RDFD_OFFSET 0x00001000 /**< Axi4 Receive Data */ -#define XLLF_RLF_OFFSET 0x00000024 /**< Receive Length */ -#define XLLF_LLR_OFFSET 0x00000028 /**< Local Link Reset */ -#define XLLF_TDR_OFFSET 0x0000002C /**< Transmit Destination */ -#define XLLF_RDR_OFFSET 0x00000030 /**< Receive Destination */ - -/*@}*/ - -/* Register masks. The following constants define bit locations of various - * control bits in the registers. Constants are not defined for those registers - * that have a single bit field representing all 32 bits. For further - * information on the meaning of the various bit masks, refer to the HW spec. - */ - -/** @name Interrupt bits - * These bits are associated with the XLLF_IER_OFFSET and XLLF_ISR_OFFSET - * registers. - * @{ - */ -#define XLLF_INT_RPURE_MASK 0x80000000 /**< Receive under-read */ -#define XLLF_INT_RPORE_MASK 0x40000000 /**< Receive over-read */ -#define XLLF_INT_RPUE_MASK 0x20000000 /**< Receive underrun (empty) */ -#define XLLF_INT_TPOE_MASK 0x10000000 /**< Transmit overrun */ -#define XLLF_INT_TC_MASK 0x08000000 /**< Transmit complete */ -#define XLLF_INT_RC_MASK 0x04000000 /**< Receive complete */ -#define XLLF_INT_TSE_MASK 0x02000000 /**< Transmit length mismatch */ -#define XLLF_INT_TRC_MASK 0x01000000 /**< Transmit reset complete */ -#define XLLF_INT_RRC_MASK 0x00800000 /**< Receive reset complete */ -#define XLLF_INT_TFPF_MASK 0x00400000 /**< Tx FIFO Programmable Full, - * AXI FIFO MM2S Only */ -#define XLLF_INT_TFPE_MASK 0x00200000 /**< Tx FIFO Programmable Empty - * AXI FIFO MM2S Only */ -#define XLLF_INT_RFPF_MASK 0x00100000 /**< Rx FIFO Programmable Full - * AXI FIFO MM2S Only */ -#define XLLF_INT_RFPE_MASK 0x00080000 /**< Rx FIFO Programmable Empty - * AXI FIFO MM2S Only */ -#define XLLF_INT_ALL_MASK 0xfff80000 /**< All the ints */ -#define XLLF_INT_ERROR_MASK 0xf2000000 /**< Error status ints */ -#define XLLF_INT_RXERROR_MASK 0xe0000000 /**< Receive Error status ints */ -#define XLLF_INT_TXERROR_MASK 0x12000000 /**< Transmit Error status ints */ -/*@}*/ - -/** @name Reset register values - * These bits are associated with the XLLF_TDFR_OFFSET and XLLF_RDFR_OFFSET - * reset registers. - * @{ - */ -#define XLLF_RDFR_RESET_MASK 0x000000a5 /**< receive reset value */ -#define XLLF_TDFR_RESET_MASK 0x000000a5 /**< Transmit reset value */ -#define XLLF_LLR_RESET_MASK 0x000000a5 /**< Local Link reset value */ -/*@}*/ - -/**************************** Type Definitions *******************************/ - -/***************** Macros (Inline Functions) Definitions *********************/ - -/**** debug macros ****/ -#define XLlFifo_reg_name(RegOffset) \ - (((RegOffset) == XLLF_ISR_OFFSET) ? "ISR": \ - ((RegOffset) == XLLF_IER_OFFSET) ? "IER": \ - ((RegOffset) == XLLF_TDFR_OFFSET) ? "TDFR {tx reset}": \ - ((RegOffset) == XLLF_TDFV_OFFSET) ? "TDFV {tx vacancy}": \ - ((RegOffset) == XLLF_TDFD_OFFSET) ? "TDFD {tx data}": \ - ((RegOffset) == XLLF_TLF_OFFSET) ? "TLF {tx length}": \ - ((RegOffset) == XLLF_RDFR_OFFSET) ? "RDFR {rx reset}": \ - ((RegOffset) == XLLF_RDFO_OFFSET) ? "RDFO {rx occupancy}": \ - ((RegOffset) == XLLF_RDFD_OFFSET) ? "RDFD {rx data}": \ - ((RegOffset) == XLLF_RLF_OFFSET) ? "RLF {rx length}": \ - "unknown") - -#define XLlFifo_print_reg_o(BaseAddress, RegOffset, Value) \ - xdbg_printf(XDBG_DEBUG_FIFO_REG, "0x%08x -> %s(0x%08x)\n", (Value), \ - XLlFifo_reg_name(RegOffset), \ - (RegOffset) + (BaseAddress)) - -#define XLlFifo_print_reg_i(BaseAddress, RegOffset, Value) \ - xdbg_printf(XDBG_DEBUG_FIFO_REG, "%s(0x%08x) -> 0x%08x\n", \ - XLlFifo_reg_name(RegOffset), \ - (RegOffset) + (BaseAddress), (Value)) -/**** end debug macros ****/ - -/****************************************************************************/ -/** -* -* XLlFifo_ReadReg returns the value of the register at the offet, -* RegOffset, from the memory mapped base address, BaseAddress. -* -* @param BaseAddress specifies the base address of the device. -* -* @param RegOffset specifies the offset from BaseAddress. -* -* @return XLlFifo_ReadReg returns the value of the specified register. -* -* @note -* C-style signature: -* u32 XLlFifo_ReadReg(u32 BaseAddress, u32 RegOffset) -* -*****************************************************************************/ -#ifdef DEBUG -extern u32 _xllfifo_rr_value; -#define XLlFifo_ReadReg(BaseAddress, RegOffset) \ - ((((RegOffset) > 0x24) ? xdbg_printf(XDBG_DEBUG_ERROR, \ - "XLlFifo_WriteReg: Woah! wrong reg addr: 0x%08x\n", \ - (RegOffset)) : 0), \ - _xllfifo_rr_value = Xil_In32((BaseAddress) + (RegOffset)), \ - XLlFifo_print_reg_i((BaseAddress), (RegOffset), _xllfifo_rr_value), \ - _xllfifo_rr_value) -#else -#define XLlFifo_ReadReg(BaseAddress, RegOffset) \ - (Xil_In32((BaseAddress) + (RegOffset))) -#endif - -/****************************************************************************/ -/** -* -* XLlFifo_WriteReg writes the value, Value, to the register at the -* offet, RegOffset, from the memory mapped base address, -* BaseAddress. -* -* @param BaseAddress specifies the base address of the device. -* -* @param RegOffset specifies the offset from BaseAddress. -* -* @param Value is value to write to the register. -* -* @return N/A -* -* @note -* C-style signature: -* void XLlFifo_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Value) -* -*****************************************************************************/ -#ifdef DEBUG -#define XLlFifo_WriteReg(BaseAddress, RegOffset, Value) \ - (((RegOffset) > 0x24) ? xdbg_printf(XDBG_DEBUG_ERROR, \ - "XLlFifo_WriteReg: Woah! wrong reg addr: 0x%08x\n", \ - (RegOffset)) : 0), \ - XLlFifo_print_reg_o((BaseAddress), (RegOffset), (Value)), \ - (Xil_Out32((BaseAddress) + (RegOffset), (Value))) -#else -#define XLlFifo_WriteReg(BaseAddress, RegOffset, Value) \ - ((Xil_Out32((BaseAddress) + (RegOffset), (Value)))) -#endif - -#ifdef __cplusplus -} -#endif -#endif /* XLLFIFO_HW_H end of protection macro */ -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xparameters.h b/thirdparty/libxil/include/xilinx/xparameters.h deleted file mode 100644 index 279ab6a47..000000000 --- a/thirdparty/libxil/include/xilinx/xparameters.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _X_PARAMETERS_H_ -#define _X_PARAMETERS_H_ - -/* We set all instance counters to zero - * to avoid the generation of configuration tables - * See: *_g.c, *_sinit.c source files - */ -#define XPAR_XLLFIFO_NUM_INSTANCES 0 -#define XPAR_XTMRCTR_NUM_INSTANCES 0 -#define XPAR_XAXIDMA_NUM_INSTANCES 0 -#define XPAR_XAXIS_SWITCH_NUM_INSTANCES 0 - -#define XPAR_XINTC_NUM_INSTANCES 0 -#define XPAR_INTC_MAX_NUM_INTR_INPUTS 0 - -#endif \ No newline at end of file diff --git a/thirdparty/libxil/include/xilinx/xstatus.h b/thirdparty/libxil/include/xilinx/xstatus.h deleted file mode 100644 index a8caf2f4e..000000000 --- a/thirdparty/libxil/include/xilinx/xstatus.h +++ /dev/null @@ -1,432 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xstatus.h -* @addtogroup common_v1_00_a -* @{ -* -* This file contains Xilinx software status codes. Status codes have their -* own data type called int. These codes are used throughout the Xilinx -* device drivers. -* -******************************************************************************/ - -#ifndef XSTATUS_H /* prevent circular inclusions */ -#define XSTATUS_H /* by using protection macros */ - -#ifdef __cplusplus -extern "C" { -#endif - -/***************************** Include Files *********************************/ - -#include "xbasic_types.h" - -/************************** Constant Definitions *****************************/ - -/*********************** Common statuses 0 - 500 *****************************/ - -#define XST_SUCCESS 0L -#define XST_FAILURE 1L -#define XST_DEVICE_NOT_FOUND 2L -#define XST_DEVICE_BLOCK_NOT_FOUND 3L -#define XST_INVALID_VERSION 4L -#define XST_DEVICE_IS_STARTED 5L -#define XST_DEVICE_IS_STOPPED 6L -#define XST_FIFO_ERROR 7L /* an error occurred during an - operation with a FIFO such as - an underrun or overrun, this - error requires the device to - be reset */ -#define XST_RESET_ERROR 8L /* an error occurred which requires - the device to be reset */ -#define XST_DMA_ERROR 9L /* a DMA error occurred, this error - typically requires the device - using the DMA to be reset */ -#define XST_NOT_POLLED 10L /* the device is not configured for - polled mode operation */ -#define XST_FIFO_NO_ROOM 11L /* a FIFO did not have room to put - the specified data into */ -#define XST_BUFFER_TOO_SMALL 12L /* the buffer is not large enough - to hold the expected data */ -#define XST_NO_DATA 13L /* there was no data available */ -#define XST_REGISTER_ERROR 14L /* a register did not contain the - expected value */ -#define XST_INVALID_PARAM 15L /* an invalid parameter was passed - into the function */ -#define XST_NOT_SGDMA 16L /* the device is not configured for - scatter-gather DMA operation */ -#define XST_LOOPBACK_ERROR 17L /* a loopback test failed */ -#define XST_NO_CALLBACK 18L /* a callback has not yet been - registered */ -#define XST_NO_FEATURE 19L /* device is not configured with - the requested feature */ -#define XST_NOT_INTERRUPT 20L /* device is not configured for - interrupt mode operation */ -#define XST_DEVICE_BUSY 21L /* device is busy */ -#define XST_ERROR_COUNT_MAX 22L /* the error counters of a device - have maxed out */ -#define XST_IS_STARTED 23L /* used when part of device is - already started i.e. - sub channel */ -#define XST_IS_STOPPED 24L /* used when part of device is - already stopped i.e. - sub channel */ -#define XST_DATA_LOST 26L /* driver defined error */ -#define XST_RECV_ERROR 27L /* generic receive error */ -#define XST_SEND_ERROR 28L /* generic transmit error */ -#define XST_NOT_ENABLED 29L /* a requested service is not - available because it has not - been enabled */ - -/***************** Utility Component statuses 401 - 500 *********************/ - -#define XST_MEMTEST_FAILED 401L /* memory test failed */ - - -/***************** Common Components statuses 501 - 1000 *********************/ - -/********************* Packet Fifo statuses 501 - 510 ************************/ - -#define XST_PFIFO_LACK_OF_DATA 501L /* not enough data in FIFO */ -#define XST_PFIFO_NO_ROOM 502L /* not enough room in FIFO */ -#define XST_PFIFO_BAD_REG_VALUE 503L /* self test, a register value - was invalid after reset */ -#define XST_PFIFO_ERROR 504L /* generic packet FIFO error */ -#define XST_PFIFO_DEADLOCK 505L /* packet FIFO is reporting - * empty and full simultaneously - */ - -/************************** DMA statuses 511 - 530 ***************************/ - -#define XST_DMA_TRANSFER_ERROR 511L /* self test, DMA transfer - failed */ -#define XST_DMA_RESET_REGISTER_ERROR 512L /* self test, a register value - was invalid after reset */ -#define XST_DMA_SG_LIST_EMPTY 513L /* scatter gather list contains - no buffer descriptors ready - to be processed */ -#define XST_DMA_SG_IS_STARTED 514L /* scatter gather not stopped */ -#define XST_DMA_SG_IS_STOPPED 515L /* scatter gather not running */ -#define XST_DMA_SG_LIST_FULL 517L /* all the buffer desciptors of - the scatter gather list are - being used */ -#define XST_DMA_SG_BD_LOCKED 518L /* the scatter gather buffer - descriptor which is to be - copied over in the scatter - list is locked */ -#define XST_DMA_SG_NOTHING_TO_COMMIT 519L /* no buffer descriptors have been - put into the scatter gather - list to be commited */ -#define XST_DMA_SG_COUNT_EXCEEDED 521L /* the packet count threshold - specified was larger than the - total # of buffer descriptors - in the scatter gather list */ -#define XST_DMA_SG_LIST_EXISTS 522L /* the scatter gather list has - already been created */ -#define XST_DMA_SG_NO_LIST 523L /* no scatter gather list has - been created */ -#define XST_DMA_SG_BD_NOT_COMMITTED 524L /* the buffer descriptor which was - being started was not committed - to the list */ -#define XST_DMA_SG_NO_DATA 525L /* the buffer descriptor to start - has already been used by the - hardware so it can't be reused - */ -#define XST_DMA_SG_LIST_ERROR 526L /* general purpose list access - error */ -#define XST_DMA_BD_ERROR 527L /* general buffer descriptor - error */ - -/************************** IPIF statuses 531 - 550 ***************************/ - -#define XST_IPIF_REG_WIDTH_ERROR 531L /* an invalid register width - was passed into the function */ -#define XST_IPIF_RESET_REGISTER_ERROR 532L /* the value of a register at - reset was not valid */ -#define XST_IPIF_DEVICE_STATUS_ERROR 533L /* a write to the device interrupt - status register did not read - back correctly */ -#define XST_IPIF_DEVICE_ACK_ERROR 534L /* the device interrupt status - register did not reset when - acked */ -#define XST_IPIF_DEVICE_ENABLE_ERROR 535L /* the device interrupt enable - register was not updated when - other registers changed */ -#define XST_IPIF_IP_STATUS_ERROR 536L /* a write to the IP interrupt - status register did not read - back correctly */ -#define XST_IPIF_IP_ACK_ERROR 537L /* the IP interrupt status register - did not reset when acked */ -#define XST_IPIF_IP_ENABLE_ERROR 538L /* IP interrupt enable register was - not updated correctly when other - registers changed */ -#define XST_IPIF_DEVICE_PENDING_ERROR 539L /* The device interrupt pending - register did not indicate the - expected value */ -#define XST_IPIF_DEVICE_ID_ERROR 540L /* The device interrupt ID register - did not indicate the expected - value */ -#define XST_IPIF_ERROR 541L /* generic ipif error */ - -/****************** Device specific statuses 1001 - 4095 *********************/ - -/********************* Ethernet statuses 1001 - 1050 *************************/ - -#define XST_EMAC_MEMORY_SIZE_ERROR 1001L /* Memory space is not big enough - * to hold the minimum number of - * buffers or descriptors */ -#define XST_EMAC_MEMORY_ALLOC_ERROR 1002L /* Memory allocation failed */ -#define XST_EMAC_MII_READ_ERROR 1003L /* MII read error */ -#define XST_EMAC_MII_BUSY 1004L /* An MII operation is in progress */ -#define XST_EMAC_OUT_OF_BUFFERS 1005L /* Driver is out of buffers */ -#define XST_EMAC_PARSE_ERROR 1006L /* Invalid driver init string */ -#define XST_EMAC_COLLISION_ERROR 1007L /* Excess deferral or late - * collision on polled send */ - -/*********************** UART statuses 1051 - 1075 ***************************/ -#define XST_UART - -#define XST_UART_INIT_ERROR 1051L -#define XST_UART_START_ERROR 1052L -#define XST_UART_CONFIG_ERROR 1053L -#define XST_UART_TEST_FAIL 1054L -#define XST_UART_BAUD_ERROR 1055L -#define XST_UART_BAUD_RANGE 1056L - - -/************************ IIC statuses 1076 - 1100 ***************************/ - -#define XST_IIC_SELFTEST_FAILED 1076 /* self test failed */ -#define XST_IIC_BUS_BUSY 1077 /* bus found busy */ -#define XST_IIC_GENERAL_CALL_ADDRESS 1078 /* mastersend attempted with */ - /* general call address */ -#define XST_IIC_STAND_REG_RESET_ERROR 1079 /* A non parameterizable reg */ - /* value after reset not valid */ -#define XST_IIC_TX_FIFO_REG_RESET_ERROR 1080 /* Tx fifo included in design */ - /* value after reset not valid */ -#define XST_IIC_RX_FIFO_REG_RESET_ERROR 1081 /* Rx fifo included in design */ - /* value after reset not valid */ -#define XST_IIC_TBA_REG_RESET_ERROR 1082 /* 10 bit addr incl in design */ - /* value after reset not valid */ -#define XST_IIC_CR_READBACK_ERROR 1083 /* Read of the control register */ - /* didn't return value written */ -#define XST_IIC_DTR_READBACK_ERROR 1084 /* Read of the data Tx reg */ - /* didn't return value written */ -#define XST_IIC_DRR_READBACK_ERROR 1085 /* Read of the data Receive reg */ - /* didn't return value written */ -#define XST_IIC_ADR_READBACK_ERROR 1086 /* Read of the data Tx reg */ - /* didn't return value written */ -#define XST_IIC_TBA_READBACK_ERROR 1087 /* Read of the 10 bit addr reg */ - /* didn't return written value */ -#define XST_IIC_NOT_SLAVE 1088 /* The device isn't a slave */ - -/*********************** ATMC statuses 1101 - 1125 ***************************/ - -#define XST_ATMC_ERROR_COUNT_MAX 1101L /* the error counters in the ATM - controller hit the max value - which requires the statistics - to be cleared */ - -/*********************** Flash statuses 1126 - 1150 **************************/ - -#define XST_FLASH_BUSY 1126L /* Flash is erasing or programming - */ -#define XST_FLASH_READY 1127L /* Flash is ready for commands */ -#define XST_FLASH_ERROR 1128L /* Flash had detected an internal - error. Use XFlash_DeviceControl - to retrieve device specific codes - */ -#define XST_FLASH_ERASE_SUSPENDED 1129L /* Flash is in suspended erase state - */ -#define XST_FLASH_WRITE_SUSPENDED 1130L /* Flash is in suspended write state - */ -#define XST_FLASH_PART_NOT_SUPPORTED 1131L /* Flash type not supported by - driver */ -#define XST_FLASH_NOT_SUPPORTED 1132L /* Operation not supported */ -#define XST_FLASH_TOO_MANY_REGIONS 1133L /* Too many erase regions */ -#define XST_FLASH_TIMEOUT_ERROR 1134L /* Programming or erase operation - aborted due to a timeout */ -#define XST_FLASH_ADDRESS_ERROR 1135L /* Accessed flash outside its - addressible range */ -#define XST_FLASH_ALIGNMENT_ERROR 1136L /* Write alignment error */ -#define XST_FLASH_BLOCKING_CALL_ERROR 1137L /* Couldn't return immediately from - write/erase function with - XFL_NON_BLOCKING_WRITE/ERASE - option cleared */ -#define XST_FLASH_CFI_QUERY_ERROR 1138L /* Failed to query the device */ - -/*********************** SPI statuses 1151 - 1175 ****************************/ - -#define XST_SPI_MODE_FAULT 1151 /* master was selected as slave */ -#define XST_SPI_TRANSFER_DONE 1152 /* data transfer is complete */ -#define XST_SPI_TRANSMIT_UNDERRUN 1153 /* slave underruns transmit register */ -#define XST_SPI_RECEIVE_OVERRUN 1154 /* device overruns receive register */ -#define XST_SPI_NO_SLAVE 1155 /* no slave has been selected yet */ -#define XST_SPI_TOO_MANY_SLAVES 1156 /* more than one slave is being - * selected */ -#define XST_SPI_NOT_MASTER 1157 /* operation is valid only as master */ -#define XST_SPI_SLAVE_ONLY 1158 /* device is configured as slave-only - */ -#define XST_SPI_SLAVE_MODE_FAULT 1159 /* slave was selected while disabled */ -#define XST_SPI_SLAVE_MODE 1160 /* device has been addressed as slave */ -#define XST_SPI_RECEIVE_NOT_EMPTY 1161 /* device received data in slave mode */ - -#define XST_SPI_COMMAND_ERROR 1162 /* unrecognised command - qspi only */ - -/********************** OPB Arbiter statuses 1176 - 1200 *********************/ - -#define XST_OPBARB_INVALID_PRIORITY 1176 /* the priority registers have either - * one master assigned to two or more - * priorities, or one master not - * assigned to any priority - */ -#define XST_OPBARB_NOT_SUSPENDED 1177 /* an attempt was made to modify the - * priority levels without first - * suspending the use of priority - * levels - */ -#define XST_OPBARB_PARK_NOT_ENABLED 1178 /* bus parking by id was enabled but - * bus parking was not enabled - */ -#define XST_OPBARB_NOT_FIXED_PRIORITY 1179 /* the arbiter must be in fixed - * priority mode to allow the - * priorities to be changed - */ - -/************************ Intc statuses 1201 - 1225 **************************/ - -#define XST_INTC_FAIL_SELFTEST 1201 /* self test failed */ -#define XST_INTC_CONNECT_ERROR 1202 /* interrupt already in use */ - -/********************** TmrCtr statuses 1226 - 1250 **************************/ - -#define XST_TMRCTR_TIMER_FAILED 1226 /* self test failed */ - -/********************** WdtTb statuses 1251 - 1275 ***************************/ - -#define XST_WDTTB_TIMER_FAILED 1251L - -/********************** PlbArb statuses 1276 - 1300 **************************/ - -#define XST_PLBARB_FAIL_SELFTEST 1276L - -/********************** Plb2Opb statuses 1301 - 1325 *************************/ - -#define XST_PLB2OPB_FAIL_SELFTEST 1301L - -/********************** Opb2Plb statuses 1326 - 1350 *************************/ - -#define XST_OPB2PLB_FAIL_SELFTEST 1326L - -/********************** SysAce statuses 1351 - 1360 **************************/ - -#define XST_SYSACE_NO_LOCK 1351L /* No MPU lock has been granted */ - -/********************** PCI Bridge statuses 1361 - 1375 **********************/ - -#define XST_PCI_INVALID_ADDRESS 1361L - -/********************** FlexRay constants 1400 - 1409 *************************/ - -#define XST_FR_TX_ERROR 1400 -#define XST_FR_TX_BUSY 1401 -#define XST_FR_BUF_LOCKED 1402 -#define XST_FR_NO_BUF 1403 - -/****************** USB constants 1410 - 1420 *******************************/ - -#define XST_USB_ALREADY_CONFIGURED 1410 -#define XST_USB_BUF_ALIGN_ERROR 1411 -#define XST_USB_NO_DESC_AVAILABLE 1412 -#define XST_USB_BUF_TOO_BIG 1413 -#define XST_USB_NO_BUF 1414 - -/****************** HWICAP constants 1421 - 1429 *****************************/ - -#define XST_HWICAP_WRITE_DONE 1421 - - -/****************** AXI VDMA constants 1430 - 1440 *****************************/ - -#define XST_VDMA_MISMATCH_ERROR 1430 - -/*********************** NAND Flash statuses 1441 - 1459 *********************/ - -#define XST_NAND_BUSY 1441L /* Flash is erasing or - * programming - */ -#define XST_NAND_READY 1442L /* Flash is ready for commands - */ -#define XST_NAND_ERROR 1443L /* Flash had detected an - * internal error. - */ -#define XST_NAND_PART_NOT_SUPPORTED 1444L /* Flash type not supported by - * driver - */ -#define XST_NAND_OPT_NOT_SUPPORTED 1445L /* Operation not supported - */ -#define XST_NAND_TIMEOUT_ERROR 1446L /* Programming or erase - * operation aborted due to a - * timeout - */ -#define XST_NAND_ADDRESS_ERROR 1447L /* Accessed flash outside its - * addressible range - */ -#define XST_NAND_ALIGNMENT_ERROR 1448L /* Write alignment error - */ -#define XST_NAND_PARAM_PAGE_ERROR 1449L /* Failed to read parameter - * page of the device - */ -#define XST_NAND_CACHE_ERROR 1450L /* Flash page buffer error - */ - -#define XST_NAND_WRITE_PROTECTED 1451L /* Flash is write protected - */ - -/**************************** Type Definitions *******************************/ - -typedef int XStatus; - -/***************** Macros (Inline Functions) Definitions *********************/ - - -/************************** Function Prototypes ******************************/ - -#ifdef __cplusplus -} -#endif - -#endif /* end of protection macro */ -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xstreamer.h b/thirdparty/libxil/include/xilinx/xstreamer.h deleted file mode 100644 index bbb65f0e9..000000000 --- a/thirdparty/libxil/include/xilinx/xstreamer.h +++ /dev/null @@ -1,333 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2005 - 2014 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/* - * - * @file xstreamer.h -* @addtogroup llfifo_v5_0 -* @{ - * - * The Xilinx byte streamer for packet FIFOs. - * - *

Driver Description

- * - * This driver enables higher layer software to access a hardware FIFO using - * any alignment in the data buffers while preserving alignment for the hardware - * FIFO access. - * - * This driver treats send and receive channels separately, using different - * types of instance objects for each. - * - * This driver makes use of another FIFO driver to access the specific FIFO - * hardware through use of the routines passed into the Tx/RxInitialize - * routines. - * - *

Initialization

- * - * Send and receive channels are intialized separately. The receive channel is - * initiailzed using XStrm_RxInitialize(). The send channel is initialized - * using XStrm_TxInitialize(). - * - * - *

Usage

- * It is fairly simple to use the API provided by this byte streamer - * driver. The only somewhat tricky part is that the calling code must - * correctly call a couple routines in the right sequence for receive and - * transmit. - * - * This sequence is described here. Check the routine functional - * descriptions for information on how to use a specific API routine. - * - *

Receive

- * A frame is received by using the following sequence:
- * 1) call XStrm_RxGetLen() to get the length of the next incoming frame.
- * 2) call XStrm_Read() one or more times to read the number of bytes - * reported by XStrm_RxGetLen().
- * - * For example: - *
- * 	frame_len = XStrm_RxGetLen(&RxInstance);
- * 	while (frame_len) {
- * 		unsigned bytes = min(sizeof(buffer), frame_len);
- * 		XStrm_Read(&RxInstance, buffer, bytes);
- * 		// do something with buffer here
- * 		frame_len -= bytes;
- * 	}
- * 
- * - * Other restrictions on the sequence of API calls may apply depending on - * the specific FIFO driver used by this byte streamer driver. - * - *

Transmit

- * A frame is transmittted by using the following sequence:
- * 1) call XStrm_Write() one or more times to write all the of bytes in - * the next frame.
- * 2) call XStrm_TxSetLen() to begin the transmission of frame just - * written.
- * - * For example: - *
- * 	frame_left = frame_len;
- * 	while (frame_left) {
- * 		unsigned bytes = min(sizeof(buffer), frame_left);
- * 		XStrm_Write(&TxInstance, buffer, bytes);
- * 		// do something here to refill buffer
- * 	}
- * 	XStrm_TxSetLen(&RxInstance, frame_len);
- * 
- * - * Other restrictions on the sequence of API calls may apply depending on - * the specific FIFO driver used by this byte streamer driver. - * - *
- * MODIFICATION HISTORY:
- *
- * Ver   Who  Date     Changes
- * ----- ---- -------- -------------------------------------------------------
- * 1.00a jvb  10/12/06 First release
- * 1.02a jz   12/04/09  Hal phase 1 support
- * 2.00a hbm  01/20/10  Hal phase 1 support, bump up major release
- * 2.02a asa  12/28/11  The macro XStrm_IsRxInternalEmpty is changed to use
- *			FrmByteCnt instead of HeadIndex.
- * 
- * - *****************************************************************************/ -#ifndef XSTREAMER_H /* prevent circular inclusions */ -#define XSTREAMER_H /* by using preprocessor symbols */ - -/* force C linkage */ -#ifdef __cplusplus -extern "C" { -#endif - -#include "xenv.h" -#include "xdebug.h" -#include "xil_types.h" - -/* - * key hole size in 32 bit words - */ -#define LARGEST_FIFO_KEYHOLE_SIZE_WORDS 4 - -/* - * This union is used simply to force a 32bit alignment on the - * buffer. Only the 'bytes' member is really used. - */ -union XStrm_AlignedBufferType { - u32 _words[LARGEST_FIFO_KEYHOLE_SIZE_WORDS]; - char bytes[LARGEST_FIFO_KEYHOLE_SIZE_WORDS * 4]; -}; - -typedef int(*XStrm_XferFnType) (void *FifoInstance, void *BufPtr, - unsigned WordCount); -typedef u32 (*XStrm_GetLenFnType) (void *FifoInstance); -typedef void (*XStrm_SetLenFnType) (void *FifoInstance, - u32 ByteCount); -typedef u32 (*XStrm_GetOccupancyFnType) (void *FifoInstance); -typedef u32 (*XStrm_GetVacancyFnType) (void *FifoInstance); - -/** - * This typedef defines a run-time instance of a receive byte-streamer. - */ -typedef struct XStrm_RxFifoStreamer { - union XStrm_AlignedBufferType AlignedBuffer; - unsigned HeadIndex; /**< HeadIndex is the index to the AlignedBuffer - * as bytes. - */ - unsigned FifoWidth; /**< FifoWidth is the FIFO key hole width in bytes. - */ - unsigned FrmByteCnt; /**< FrmByteCnt is the number of bytes in the next - * Frame. - */ - void *FifoInstance; /**< FifoInstance is the FIFO driver instance to - * pass to ReadFn, GetLenFn, and GetOccupancyFn - * routines. - */ - XStrm_XferFnType ReadFn; /**< ReadFn is the routine the streamer - * uses to receive bytes from the Fifo. - */ - XStrm_GetLenFnType GetLenFn; /**< GetLenFn is the routine the streamer - * uses to initiate receive operations - * on the FIFO. - */ - XStrm_GetOccupancyFnType GetOccupancyFn; /**< GetOccupancyFn is the - * routine the streamer uses - * to get the occupancy from - * the FIFO. - */ -} XStrm_RxFifoStreamer; - -/** - * This typedef defines a run-time instance of a transmit byte-streamer. - */ -typedef struct XStrm_TxFifoStreamer { - union XStrm_AlignedBufferType AlignedBuffer; - unsigned TailIndex; /**< TailIndex is the index to the AlignedBuffer - * as bytes - */ - unsigned FifoWidth; /**< FifoWidth is the FIFO key hole width in bytes. - */ - - void *FifoInstance; /**< FifoInstance is the FIFO driver instance to - * pass to WriteFn, SetLenFn, and GetVacancyFn - * routines. - */ - XStrm_XferFnType WriteFn; /**< WriteFn is the routine the streamer - * uses to transmit bytes to the Fifo. - */ - XStrm_SetLenFnType SetLenFn; /**< SetLenFn is the routine the streamer - * uses to initiate transmit operations - * on the FIFO. - */ - XStrm_GetVacancyFnType GetVacancyFn; /**< GetVaccancyFn is the routine - * the streamer uses to get the - * vacancy from the FIFO. - */ -} XStrm_TxFifoStreamer; - -/*****************************************************************************/ -/* -* -* XStrm_TxVacancy returns the number of unused 32-bit words available (vacancy) -* between the streamer, specified by InstancePtr, and the FIFO this -* streamer is using. -* -* @param InstancePtr references the streamer on which to operate. -* -* @return XStrm_TxVacancy returns the vacancy count in number of 32 bit words. -* -* @note -* -* C Signature: u32 XStrm_TxVacancy(XStrm_TxFifoStreamer *InstancePtr) -* -* The amount of bytes in the holding buffer (rounded up to whole 32-bit words) -* is subtracted from the vacancy value of FIFO this streamer is using. This is -* to ensure the caller can write the number words given in the return value and -* not overflow the FIFO. -* -******************************************************************************/ -#define XStrm_TxVacancy(InstancePtr) \ - (((*(InstancePtr)->GetVacancyFn)((InstancePtr)->FifoInstance)) - \ - (((InstancePtr)->TailIndex + 3) / 4)) - -/*****************************************************************************/ -/* -* -* XStrm_RxOccupancy returns the number of 32-bit words available (occupancy) to -* be read from the streamer, specified by InstancePtr, and FIFO this -* steamer is using. -* -* @param InstancePtr references the streamer on which to operate. -* -* @return XStrm_RxOccupancy returns the occupancy count in number of 32 bit -* words. -* -* @note -* -* C Signature: u32 XStrm_RxOccupancy(XStrm_RxFifoStreamer *InstancePtr) -* -* The amount of bytes in the holding buffer (rounded up to whole 32-bit words) -* is added to the occupancy value of FIFO this streamer is using. This is to -* ensure the caller will get a little more accurate occupancy value. -* -******************************************************************************/ -#ifdef DEBUG -extern u32 _xstrm_ro_value; -extern u32 _xstrm_buffered; -#define XStrm_RxOccupancy(InstancePtr) \ - (_xstrm_ro_value = ((*(InstancePtr)->GetOccupancyFn)((InstancePtr)->FifoInstance)), \ - xdbg_printf(XDBG_DEBUG_FIFO_RX, "reg: %d; frmbytecnt: %d\n", \ - _xstrm_ro_value, (InstancePtr)->FrmByteCnt), \ - (((InstancePtr)->FrmByteCnt) ? \ - _xstrm_buffered = ((InstancePtr)->FifoWidth - (InstancePtr)->HeadIndex) : \ - 0), \ - xdbg_printf(XDBG_DEBUG_FIFO_RX, "buffered_bytes: %d\n", _xstrm_buffered), \ - xdbg_printf(XDBG_DEBUG_FIFO_RX, "buffered (rounded): %d\n", _xstrm_buffered), \ - (_xstrm_ro_value + _xstrm_buffered)) -#else -#define XStrm_RxOccupancy(InstancePtr) \ - ( \ - ((*(InstancePtr)->GetOccupancyFn)((InstancePtr)->FifoInstance)) + \ - ( \ - ((InstancePtr)->FrmByteCnt) ? \ - ((InstancePtr)->FifoWidth - (InstancePtr)->HeadIndex) : \ - 0 \ - ) \ - ) -#endif - -/****************************************************************************/ -/* -* -* XStrm_IsRxInternalEmpty returns true if the streamer, specified by -* InstancePtr, is not holding any bytes in it's internal buffers. Note -* that this routine does not reflect information about the state of the -* FIFO used by this streamer. -* -* @param InstancePtr references the streamer on which to operate. -* -* @return XStrm_IsRxInternalEmpty returns TRUE when the streamer is not -* holding any bytes in it's internal buffers. Otherwise, -* XStrm_IsRxInternalEmpty returns FALSE. -* -* @note -* C-style signature: -* int XStrm_IsRxInternalEmpty(XStrm_RxFifoStreamer *InstancePtr) -* -*****************************************************************************/ -#define XStrm_IsRxInternalEmpty(InstancePtr) \ - (((InstancePtr)->FrmByteCnt == 0) ? TRUE : FALSE) - -void XStrm_RxInitialize(XStrm_RxFifoStreamer *InstancePtr, - unsigned FifoWidth, void *FifoInstance, - XStrm_XferFnType ReadFn, - XStrm_GetLenFnType GetLenFn, - XStrm_GetOccupancyFnType GetOccupancyFn); - -void XStrm_TxInitialize(XStrm_TxFifoStreamer *InstancePtr, - unsigned FifoWidth, void *FifoInstance, - XStrm_XferFnType WriteFn, - XStrm_SetLenFnType SetLenFn, - XStrm_GetVacancyFnType GetVacancyFn); - -void XStrm_TxSetLen(XStrm_TxFifoStreamer *InstancePtr, u32 Bytes); -void XStrm_Write(XStrm_TxFifoStreamer *InstancePtr, void *BufPtr, - unsigned bytes); - -u32 XStrm_RxGetLen(XStrm_RxFifoStreamer *InstancePtr); -void XStrm_Read(XStrm_RxFifoStreamer *InstancePtr, void *BufPtr, - unsigned bytes); - -#ifdef __cplusplus -} -#endif -#endif /* XSTREAMER_H end of preprocessor protection symbols */ -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xtmrctr.h b/thirdparty/libxil/include/xilinx/xtmrctr.h deleted file mode 100644 index 5b8238043..000000000 --- a/thirdparty/libxil/include/xilinx/xtmrctr.h +++ /dev/null @@ -1,303 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2002 - 2015 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xtmrctr.h -* @addtogroup tmrctr_v4_0 -* @{ -* @details -* -* The Xilinx timer/counter component. This component supports the Xilinx -* timer/counter. More detailed description of the driver operation can -* be found in the xtmrctr.c file. -* -* The Xilinx timer/counter supports the following features: -* - Polled mode. -* - Interrupt driven mode -* - enabling and disabling specific timers -* - PWM operation -* - Cascade Operation (This is to be used for getting a 64 bit timer and this -* feature is present in the latest versions of the axi_timer IP) -* -* The driver does not currently support the PWM operation of the device. -* -* The timer counter operates in 2 primary modes, compare and capture. In -* either mode, the timer counter may count up or down, with up being the -* default. -* -* Compare mode is typically used for creating a single time period or multiple -* repeating time periods in the auto reload mode, such as a periodic interrupt. -* When started, the timer counter loads an initial value, referred to as the -* compare value, into the timer counter and starts counting down or up. The -* timer counter expires when it rolls over/under depending upon the mode of -* counting. An external compare output signal may be configured such that a -* pulse is generated with this signal when it hits the compare value. -* -* Capture mode is typically used for measuring the time period between -* external events. This mode uses an external capture input signal to cause -* the value of the timer counter to be captured. When started, the timer -* counter loads an initial value, referred to as the compare value, - -* The timer can be configured to either cause an interrupt when the count -* reaches the compare value in compare mode or latch the current count -* value in the capture register when an external input is asserted -* in capture mode. The external capture input can be enabled/disabled using the -* XTmrCtr_SetOptions function. While in compare mode, it is also possible to -* drive an external output when the compare value is reached in the count -* register The external compare output can be enabled/disabled using the -* XTmrCtr_SetOptions function. -* -* Interrupts -* -* It is the responsibility of the application to connect the interrupt -* handler of the timer/counter to the interrupt source. The interrupt -* handler function, XTmrCtr_InterruptHandler, is visible such that the user -* can connect it to the interrupt source. Note that this interrupt handler -* does not provide interrupt context save and restore processing, the user -* must perform this processing. -* -* The driver services interrupts and passes timeouts to the upper layer -* software through callback functions. The upper layer software must register -* its callback functions during initialization. The driver requires callback -* functions for timers. -* -* @note -* The default settings for the timers are: -* - Interrupt generation disabled -* - Count up mode -* - Compare mode -* - Hold counter (will not reload the timer) -* - External compare output disabled -* - External capture input disabled -* - Pulse width modulation disabled -* - Timer disabled, waits for Start function to be called -*

-* A timer counter device may contain multiple timer counters. The symbol -* XTC_DEVICE_TIMER_COUNT defines the number of timer counters in the device. -* The device currently contains 2 timer counters. -*

-* This driver is intended to be RTOS and processor independent. It works with -* physical addresses only. Any needs for dynamic memory management, threads -* or thread mutual exclusion, virtual memory, or cache control must be -* satisfied by the layer above this driver. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who  Date     Changes
-* ----- ---- -------- -----------------------------------------------
-* 1.00a ecm  08/16/01 First release
-* 1.00b jhl  02/21/02 Repartitioned the driver for smaller files
-* 1.10b mta  03/21/07 Updated to new coding style.
-* 1.11a sdm  08/22/08 Removed support for static interrupt handlers from the MDD
-*		      file
-* 2.00a ktn  10/30/09 Updated to use HAL API's. _m is removed from all the macro
-*		      definitions.
-* 2.01a ktn  07/12/10 Renamed the macro XTimerCtr_ReadReg as XTmrCtr_ReadReg
-*		      for naming consistency (CR 559142).
-* 2.02a sdm  09/28/10 Updated the driver tcl to generate the xparameters
-*		      for the timer clock frequency (CR 572679).
-* 2.03a rvo  11/30/10 Added check to see if interrupt is enabled before further
-*		      processing for CR 584557.
-* 2.04a sdm  07/12/11 Added support for cascade mode operation.
-* 		      The cascade mode of operation is present in the latest
-*		      versions of the axi_timer IP. Please check the HW
-*		      Datasheet to see whether this feature is present in the
-*		      version of the IP that you are using.
-* 2.05a adk  15/05/13 Fixed the CR:693066
-*		      Added the IsStartedTmrCtr0/IsStartedTmrCtr1 members to the
-*		      XTmrCtr instance structure.
-*		      The IsStartedTmrCtrX will be assigned XIL_COMPONENT_IS_STARTED in
-*		      the XTmrCtr_Start function.
-*		      The IsStartedTmrCtrX will be cleared in the XTmrCtr_Stop function.
-*		      There will be no Initialization done in the
-*		      XTmrCtr_Initialize if both the timers have already started and
-*		      the XST_DEVICE_IS_STARTED Status is returned.
-*		      Removed the logic in the XTmrCtr_Initialize function
-*		      which was checking the Register Value to know whether
-*		      a timer has started or not.
-* 3.0   adk  19/12/13 Updated as per the New Tcl API's
-* 4.0   als  09/30/15 Updated initialization API.
-* 
-* -******************************************************************************/ - -#ifndef XTMRCTR_H /* prevent circular inclusions */ -#define XTMRCTR_H /* by using protection macros */ - -#ifdef __cplusplus -extern "C" { -#endif - -/***************************** Include Files *********************************/ - -#include "xil_types.h" -#include "xil_assert.h" -#include "xstatus.h" -#include "xtmrctr_l.h" - -/************************** Constant Definitions *****************************/ - -/** - * @name Configuration options - * These options are used in XTmrCtr_SetOptions() and XTmrCtr_GetOptions() - * @{ - */ -/** - * Used to configure the timer counter device. - *
- * XTC_CASCADE_MODE_OPTION	Enables the Cascade Mode only valid for TCSRO.
- * XTC_ENABLE_ALL_OPTION	Enables all timer counters at once.
- * XTC_DOWN_COUNT_OPTION	Configures the timer counter to count down from
- *				start value, the default is to count up.
- * XTC_CAPTURE_MODE_OPTION	Configures the timer to capture the timer
- *				counter value when the external capture line is
- *				asserted. The default mode is compare mode.
- * XTC_INT_MODE_OPTION		Enables the timer counter interrupt output.
- * XTC_AUTO_RELOAD_OPTION	In compare mode, configures the timer counter to
- *				reload from the compare value. The default mode
- *				causes the timer counter to hold when the
- *				compare value is hit.
- *				In capture mode, configures the timer counter to
- *				not hold the previous capture value if a new
- *				event occurs. The default mode cause the timer
- *				counter to hold the capture value until
- *				recognized.
- * XTC_EXT_COMPARE_OPTION	Enables the external compare output signal.
- * 
- */ -#define XTC_CASCADE_MODE_OPTION 0x00000080UL -#define XTC_ENABLE_ALL_OPTION 0x00000040UL -#define XTC_DOWN_COUNT_OPTION 0x00000020UL -#define XTC_CAPTURE_MODE_OPTION 0x00000010UL -#define XTC_INT_MODE_OPTION 0x00000008UL -#define XTC_AUTO_RELOAD_OPTION 0x00000004UL -#define XTC_EXT_COMPARE_OPTION 0x00000002UL -/*@}*/ - -/**************************** Type Definitions *******************************/ - -/** - * This typedef contains configuration information for the device. - */ -typedef struct { - u16 DeviceId; /**< Unique ID of device */ - u32 BaseAddress; /**< Register base address */ - u32 SysClockFreqHz; /**< The AXI bus clock frequency */ -} XTmrCtr_Config; - -/** - * Signature for the callback function. - * - * @param CallBackRef is a callback reference passed in by the upper layer - * when setting the callback functions, and passed back to the - * upper layer when the callback is invoked. Its type is - * unimportant to the driver, so it is a void pointer. - * @param TmrCtrNumber is the number of the timer/counter within the - * device. The device typically contains at least two - * timer/counters. The timer number is a zero based number with a - * range of 0 to (XTC_DEVICE_TIMER_COUNT - 1). - */ -typedef void (*XTmrCtr_Handler) (void *CallBackRef, u8 TmrCtrNumber); - - -/** - * Timer/Counter statistics - */ -typedef struct { - u32 Interrupts; /**< The number of interrupts that have occurred */ -} XTmrCtrStats; - -/** - * The XTmrCtr driver instance data. The user is required to allocate a - * variable of this type for every timer/counter device in the system. A - * pointer to a variable of this type is then passed to the driver API - * functions. - */ -typedef struct { - XTmrCtr_Config Config; /**< Core configuration. */ - XTmrCtrStats Stats; /**< Component Statistics */ - u32 BaseAddress; /**< Base address of registers */ - u32 IsReady; /**< Device is initialized and ready */ - u32 IsStartedTmrCtr0; /**< Is Timer Counter 0 started */ - u32 IsStartedTmrCtr1; /**< Is Timer Counter 1 started */ - - XTmrCtr_Handler Handler; /**< Callback function */ - void *CallBackRef; /**< Callback reference for handler */ -} XTmrCtr; - - -/***************** Macros (Inline Functions) Definitions *********************/ - - -/************************** Function Prototypes ******************************/ - -/* Required functions, in file xtmrctr.c */ -void XTmrCtr_CfgInitialize(XTmrCtr *InstancePtr, XTmrCtr_Config *ConfigPtr, - u32 EffectiveAddr); -int XTmrCtr_InitHw(XTmrCtr *InstancePtr); -int XTmrCtr_Initialize(XTmrCtr * InstancePtr, u16 DeviceId); -void XTmrCtr_Start(XTmrCtr * InstancePtr, u8 TmrCtrNumber); -void XTmrCtr_Stop(XTmrCtr * InstancePtr, u8 TmrCtrNumber); -u32 XTmrCtr_GetValue(XTmrCtr * InstancePtr, u8 TmrCtrNumber); -void XTmrCtr_SetResetValue(XTmrCtr * InstancePtr, u8 TmrCtrNumber, - u32 ResetValue); -u32 XTmrCtr_GetCaptureValue(XTmrCtr * InstancePtr, u8 TmrCtrNumber); -int XTmrCtr_IsExpired(XTmrCtr * InstancePtr, u8 TmrCtrNumber); -void XTmrCtr_Reset(XTmrCtr * InstancePtr, u8 TmrCtrNumber); - -/* Lookup configuration in xtmrctr_sinit.c */ -XTmrCtr_Config *XTmrCtr_LookupConfig(u16 DeviceId); - -/* Functions for options, in file xtmrctr_options.c */ -void XTmrCtr_SetOptions(XTmrCtr * InstancePtr, u8 TmrCtrNumber, u32 Options); -u32 XTmrCtr_GetOptions(XTmrCtr * InstancePtr, u8 TmrCtrNumber); - -/* Functions for statistics, in file xtmrctr_stats.c */ -void XTmrCtr_GetStats(XTmrCtr * InstancePtr, XTmrCtrStats * StatsPtr); -void XTmrCtr_ClearStats(XTmrCtr * InstancePtr); - -/* Functions for self-test, in file xtmrctr_selftest.c */ -int XTmrCtr_SelfTest(XTmrCtr * InstancePtr, u8 TmrCtrNumber); - -/* Functions for interrupts, in file xtmrctr_intr.c */ -void XTmrCtr_SetHandler(XTmrCtr * InstancePtr, XTmrCtr_Handler FuncPtr, - void *CallBackRef); -void XTmrCtr_InterruptHandler(void *InstancePtr); - -#ifdef __cplusplus -} -#endif - -#endif /* end of protection macro */ -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xtmrctr_i.h b/thirdparty/libxil/include/xilinx/xtmrctr_i.h deleted file mode 100644 index 6cbbc0a46..000000000 --- a/thirdparty/libxil/include/xilinx/xtmrctr_i.h +++ /dev/null @@ -1,80 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xtmrctr_i.h -* @addtogroup tmrctr_v3_0 -* @{ -* -* This file contains data which is shared between files internal to the -* XTmrCtr component. It is intended for internal use only. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who  Date     Changes
-* ----- ---- -------- -----------------------------------------------
-* 1.00b jhl  02/06/02 First release
-* 1.10b mta  03/21/07 Updated to new coding style
-* 2.00a ktn  10/30/09 _m is removed from all the macro definitions.
-* 
-* -******************************************************************************/ - -#ifndef XTMRCTR_I_H /* prevent circular inclusions */ -#define XTMRCTR_I_H /* by using protection macros */ - -#ifdef __cplusplus -extern "C" { -#endif - -/***************************** Include Files *********************************/ - -#include "xil_types.h" - -/************************** Constant Definitions *****************************/ - - -/************************** Function Prototypes ******************************/ - - -/************************** Variable Definitions *****************************/ - -extern u8 XTmrCtr_Offsets[]; - -#ifdef __cplusplus -} -#endif - -#endif -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xtmrctr_l.h b/thirdparty/libxil/include/xilinx/xtmrctr_l.h deleted file mode 100644 index f5fd773ee..000000000 --- a/thirdparty/libxil/include/xilinx/xtmrctr_l.h +++ /dev/null @@ -1,429 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2002 - 2015 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xtmrctr_l.h -* @addtogroup tmrctr_v4_0 -* @{ -* -* This header file contains identifiers and low-level driver functions (or -* macros) that can be used to access the device. The user should refer to the -* hardware device specification for more details of the device operation. -* High-level driver functions are defined in xtmrctr.h. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who  Date     Changes
-* ----- ---- -------- -----------------------------------------------
-* 1.00b jhl  04/24/02 First release
-* 1.10b mta  03/21/07 Updated to new coding style
-* 2.00a ktn  10/30/09 Updated to use HAL API's. _m is removed from all the macro
-*		      definitions.
-* 2.01a ktn  07/12/10 Renamed the macro XTimerCtr_ReadReg as XTmrCtr_ReadReg
-*		      for naming consistency (CR 559142).
-* 2.04a sdm  07/12/11 Added the CASC mode bit in the TCSRO register for the
-*		      cascade mode operation.
-*		      The cascade mode of operation is present in the latest
-*		      versions of the axi_timer IP. Please check the HW
-*		      Datasheet to see whether this feature is present in the
-*		      version of the IP that you are using.
-* 
-* -******************************************************************************/ - -#ifndef XTMRCTR_L_H /* prevent circular inclusions */ -#define XTMRCTR_L_H /* by using protection macros */ - -#ifdef __cplusplus -extern "C" { -#endif - -/***************************** Include Files *********************************/ - -#include "xil_types.h" -#include "xil_io.h" - -/************************** Constant Definitions *****************************/ - -/** - * Defines the number of timer counters within a single hardware device. This - * number is not currently parameterized in the hardware but may be in the - * future. - */ -#define XTC_DEVICE_TIMER_COUNT 2 - -/* Each timer counter consumes 16 bytes of address space */ - -#define XTC_TIMER_COUNTER_OFFSET 16 - -/** @name Register Offset Definitions - * Register offsets within a timer counter, there are multiple - * timer counters within a single device - * @{ - */ - -#define XTC_TCSR_OFFSET 0 /**< Control/Status register */ -#define XTC_TLR_OFFSET 4 /**< Load register */ -#define XTC_TCR_OFFSET 8 /**< Timer counter register */ - -/* @} */ - -/** @name Control Status Register Bit Definitions - * Control Status Register bit masks - * Used to configure the timer counter device. - * @{ - */ - -#define XTC_CSR_CASC_MASK 0x00000800 /**< Cascade Mode */ -#define XTC_CSR_ENABLE_ALL_MASK 0x00000400 /**< Enables all timer - counters */ -#define XTC_CSR_ENABLE_PWM_MASK 0x00000200 /**< Enables the Pulse Width - Modulation */ -#define XTC_CSR_INT_OCCURED_MASK 0x00000100 /**< If bit is set, an - interrupt has occured. - If set and '1' is - written to this bit - position, bit is - cleared. */ -#define XTC_CSR_ENABLE_TMR_MASK 0x00000080 /**< Enables only the - specific timer */ -#define XTC_CSR_ENABLE_INT_MASK 0x00000040 /**< Enables the interrupt - output. */ -#define XTC_CSR_LOAD_MASK 0x00000020 /**< Loads the timer using - the load value provided - earlier in the Load - Register, - XTC_TLR_OFFSET. */ -#define XTC_CSR_AUTO_RELOAD_MASK 0x00000010 /**< In compare mode, - configures - the timer counter to - reload from the - Load Register. The - default mode - causes the timer counter - to hold when the compare - value is hit. In capture - mode, configures the - timer counter to not - hold the previous - capture value if a new - event occurs. The - default mode cause the - timer counter to hold - the capture value until - recognized. */ -#define XTC_CSR_EXT_CAPTURE_MASK 0x00000008 /**< Enables the - external input - to the timer counter. */ -#define XTC_CSR_EXT_GENERATE_MASK 0x00000004 /**< Enables the - external generate output - for the timer. */ -#define XTC_CSR_DOWN_COUNT_MASK 0x00000002 /**< Configures the timer - counter to count down - from start value, the - default is to count - up.*/ -#define XTC_CSR_CAPTURE_MODE_MASK 0x00000001 /**< Enables the timer to - capture the timer - counter value when the - external capture line is - asserted. The default - mode is compare mode.*/ -/* @} */ - -/**************************** Type Definitions *******************************/ - -extern u8 XTmrCtr_Offsets[]; - -/***************** Macros (Inline Functions) Definitions *********************/ - -/*****************************************************************************/ -/** -* Read one of the timer counter registers. -* -* @param BaseAddress contains the base address of the timer counter -* device. -* @param TmrCtrNumber contains the specific timer counter within the -* device, a zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). -* @param RegOffset contains the offset from the 1st register of the timer -* counter to select the specific register of the timer counter. -* -* @return The value read from the register, a 32 bit value. -* -* @note C-Style signature: -* u32 XTmrCtr_ReadReg(u32 BaseAddress, u8 TimerNumber, - unsigned RegOffset); -******************************************************************************/ -#define XTmrCtr_ReadReg(BaseAddress, TmrCtrNumber, RegOffset) \ - Xil_In32((BaseAddress) + XTmrCtr_Offsets[(TmrCtrNumber)] + \ - (RegOffset)) - -#ifndef XTimerCtr_ReadReg -#define XTimerCtr_ReadReg XTmrCtr_ReadReg -#endif - -/*****************************************************************************/ -/** -* Write a specified value to a register of a timer counter. -* -* @param BaseAddress is the base address of the timer counter device. -* @param TmrCtrNumber is the specific timer counter within the device, a -* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). -* @param RegOffset contain the offset from the 1st register of the timer -* counter to select the specific register of the timer counter. -* @param ValueToWrite is the 32 bit value to be written to the register. -* -* @note C-Style signature: -* void XTmrCtr_WriteReg(u32 BaseAddress, u8 TimerNumber, -* unsigned RegOffset, u32 ValueToWrite); -******************************************************************************/ -#define XTmrCtr_WriteReg(BaseAddress, TmrCtrNumber, RegOffset, ValueToWrite)\ - Xil_Out32(((BaseAddress) + XTmrCtr_Offsets[(TmrCtrNumber)] + \ - (RegOffset)), (ValueToWrite)) - -/****************************************************************************/ -/** -* -* Set the Control Status Register of a timer counter to the specified value. -* -* @param BaseAddress is the base address of the device. -* @param TmrCtrNumber is the specific timer counter within the device, a -* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). -* @param RegisterValue is the 32 bit value to be written to the register. -* -* @return None. -* -* @note C-Style signature: -* void XTmrCtr_SetControlStatusReg(u32 BaseAddress, -* u8 TmrCtrNumber,u32 RegisterValue); -*****************************************************************************/ -#define XTmrCtr_SetControlStatusReg(BaseAddress, TmrCtrNumber, RegisterValue)\ - XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ - (RegisterValue)) - -/****************************************************************************/ -/** -* -* Get the Control Status Register of a timer counter. -* -* @param BaseAddress is the base address of the device. -* @param TmrCtrNumber is the specific timer counter within the device, -* a zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). -* -* @return The value read from the register, a 32 bit value. -* -* @note C-Style signature: -* u32 XTmrCtr_GetControlStatusReg(u32 BaseAddress, -* u8 TmrCtrNumber); -*****************************************************************************/ -#define XTmrCtr_GetControlStatusReg(BaseAddress, TmrCtrNumber) \ - XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET) - -/****************************************************************************/ -/** -* -* Get the Timer Counter Register of a timer counter. -* -* @param BaseAddress is the base address of the device. -* @param TmrCtrNumber is the specific timer counter within the device, -* a zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). -* -* @return The value read from the register, a 32 bit value. -* -* @note C-Style signature: -* u32 XTmrCtr_GetTimerCounterReg(u32 BaseAddress, -* u8 TmrCtrNumber); -*****************************************************************************/ -#define XTmrCtr_GetTimerCounterReg(BaseAddress, TmrCtrNumber) \ - XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber), XTC_TCR_OFFSET) \ - -/****************************************************************************/ -/** -* -* Set the Load Register of a timer counter to the specified value. -* -* @param BaseAddress is the base address of the device. -* @param TmrCtrNumber is the specific timer counter within the device, a -* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). -* @param RegisterValue is the 32 bit value to be written to the register. -* -* @return None. -* -* @note C-Style signature: -* void XTmrCtr_SetLoadReg(u32 BaseAddress, u8 TmrCtrNumber, -* u32 RegisterValue); -*****************************************************************************/ -#define XTmrCtr_SetLoadReg(BaseAddress, TmrCtrNumber, RegisterValue) \ - XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TLR_OFFSET, \ - (RegisterValue)) - -/****************************************************************************/ -/** -* -* Get the Load Register of a timer counter. -* -* @param BaseAddress is the base address of the device. -* @param TmrCtrNumber is the specific timer counter within the device, a -* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). -* -* @return The value read from the register, a 32 bit value. -* -* @note C-Style signature: -* u32 XTmrCtr_GetLoadReg(u32 BaseAddress, u8 TmrCtrNumber); -*****************************************************************************/ -#define XTmrCtr_GetLoadReg(BaseAddress, TmrCtrNumber) \ -XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber), XTC_TLR_OFFSET) - -/****************************************************************************/ -/** -* -* Enable a timer counter such that it starts running. -* -* @param BaseAddress is the base address of the device. -* @param TmrCtrNumber is the specific timer counter within the device, a -* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). -* -* @return None. -* -* @note C-Style signature: -* void XTmrCtr_Enable(u32 BaseAddress, u8 TmrCtrNumber); -*****************************************************************************/ -#define XTmrCtr_Enable(BaseAddress, TmrCtrNumber) \ - XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ - (XTmrCtr_ReadReg((BaseAddress), ( TmrCtrNumber), \ - XTC_TCSR_OFFSET) | XTC_CSR_ENABLE_TMR_MASK)) - -/****************************************************************************/ -/** -* -* Disable a timer counter such that it stops running. -* -* @param BaseAddress is the base address of the device. -* @param TmrCtrNumber is the specific timer counter within the device, -* a zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). -* -* @return None. -* -* @note C-Style signature: -* void XTmrCtr_Disable(u32 BaseAddress, u8 TmrCtrNumber); -*****************************************************************************/ -#define XTmrCtr_Disable(BaseAddress, TmrCtrNumber) \ - XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ - (XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber),\ - XTC_TCSR_OFFSET) & ~ XTC_CSR_ENABLE_TMR_MASK)) - -/****************************************************************************/ -/** -* -* Enable the interrupt for a timer counter. -* -* @param BaseAddress is the base address of the device. -* @param TmrCtrNumber is the specific timer counter within the device, a -* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). -* -* @return None. -* -* @note C-Style signature: -* void XTmrCtr_EnableIntr(u32 BaseAddress, u8 TmrCtrNumber); -*****************************************************************************/ -#define XTmrCtr_EnableIntr(BaseAddress, TmrCtrNumber) \ - XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ - (XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber), \ - XTC_TCSR_OFFSET) | XTC_CSR_ENABLE_INT_MASK)) - -/****************************************************************************/ -/** -* -* Disable the interrupt for a timer counter. -* -* @param BaseAddress is the base address of the device. -* @param TmrCtrNumber is the specific timer counter within the device, a -* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). -* -* @return None. -* -* @note C-Style signature: -* void XTmrCtr_DisableIntr(u32 BaseAddress, u8 TmrCtrNumber); -*****************************************************************************/ -#define XTmrCtr_DisableIntr(BaseAddress, TmrCtrNumber) \ - XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ - (XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber), \ - XTC_TCSR_OFFSET) & ~ XTC_CSR_ENABLE_INT_MASK)) - -/****************************************************************************/ -/** -* -* Cause the timer counter to load it's Timer Counter Register with the value -* in the Load Register. -* -* @param BaseAddress is the base address of the device. -* @param TmrCtrNumber is the specific timer counter within the device, a -* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). -* -* @return None. -* -* @note C-Style signature: -* void XTmrCtr_LoadTimerCounterReg(u32 BaseAddress, - u8 TmrCtrNumber); -*****************************************************************************/ -#define XTmrCtr_LoadTimerCounterReg(BaseAddress, TmrCtrNumber) \ - XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ - (XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber),\ - XTC_TCSR_OFFSET) | XTC_CSR_LOAD_MASK)) - -/****************************************************************************/ -/** -* -* Determine if a timer counter event has occurred. Events are defined to be -* when a capture has occurred or the counter has roller over. -* -* @param BaseAddress is the base address of the device. -* @param TmrCtrNumber is the specific timer counter within the device, a -* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). -* -* @note C-Style signature: -* int XTmrCtr_HasEventOccurred(u32 BaseAddress, u8 TmrCtrNumber); -*****************************************************************************/ -#define XTmrCtr_HasEventOccurred(BaseAddress, TmrCtrNumber) \ - ((XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber), \ - XTC_TCSR_OFFSET) & XTC_CSR_INT_OCCURED_MASK) == \ - XTC_CSR_INT_OCCURED_MASK) - -/************************** Function Prototypes ******************************/ -/************************** Variable Definitions *****************************/ -#ifdef __cplusplus -} -#endif -#endif /* end of protection macro */ -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xutil.h b/thirdparty/libxil/include/xilinx/xutil.h deleted file mode 100644 index 082738e34..000000000 --- a/thirdparty/libxil/include/xilinx/xutil.h +++ /dev/null @@ -1,167 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* -* @file xutil.h -* @addtogroup common_v1_00_a -* @{ -* -* This file contains utility functions such as memory test functions. -* -* Memory test description -* -* A subset of the memory tests can be selected or all of the tests can be run -* in order. If there is an error detected by a subtest, the test stops and the -* failure code is returned. Further tests are not run even if all of the tests -* are selected. -* -* Subtest descriptions: -*
-* XUT_ALLMEMTESTS:
-*       Runs all of the following tests
-*
-* XUT_INCREMENT:
-*       Incrementing Value Test.
-*       This test starts at 'XUT_MEMTEST_INIT_VALUE' and uses the incrementing
-*       value as the test value for memory.
-*
-* XUT_WALKONES:
-*       Walking Ones Test.
-*       This test uses a walking '1' as the test value for memory.
-*       location 1 = 0x00000001
-*       location 2 = 0x00000002
-*       ...
-*
-* XUT_WALKZEROS:
-*       Walking Zero's Test.
-*       This test uses the inverse value of the walking ones test
-*       as the test value for memory.
-*       location 1 = 0xFFFFFFFE
-*       location 2 = 0xFFFFFFFD
-*       ...
-*
-* XUT_INVERSEADDR:
-*       Inverse Address Test.
-*       This test uses the inverse of the address of the location under test
-*       as the test value for memory.
-*
-* XUT_FIXEDPATTERN:
-*       Fixed Pattern Test.
-*       This test uses the provided patters as the test value for memory.
-*       If zero is provided as the pattern the test uses '0xDEADBEEF".
-* 
-* -* WARNING -* -* The tests are DESTRUCTIVE. Run before any initialized memory spaces -* have been set up. -* -* The address, Addr, provided to the memory tests is not checked for -* validity except for the NULL case. It is possible to provide a code-space -* pointer for this test to start with and ultimately destroy executable code -* causing random failures. -* -* @note -* -* Used for spaces where the address range of the region is smaller than -* the data width. If the memory range is greater than 2 ** width, -* the patterns used in XUT_WALKONES and XUT_WALKZEROS will repeat on a -* boundry of a power of two making it more difficult to detect addressing -* errors. The XUT_INCREMENT and XUT_INVERSEADDR tests suffer the same -* problem. Ideally, if large blocks of memory are to be tested, break -* them up into smaller regions of memory to allow the test patterns used -* not to repeat over the region tested. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver    Who    Date    Changes
-* ----- ---- -------- -----------------------------------------------
-* 1.00a ecm  11/01/01 First release
-* 1.00a xd   11/03/04 Improved support for doxygen.
-* 
-* -******************************************************************************/ - -#ifndef XUTIL_H /* prevent circular inclusions */ -#define XUTIL_H /* by using protection macros */ - -#ifdef __cplusplus -extern "C" { -#endif - -/***************************** Include Files *********************************/ -#include "xbasic_types.h" -#include "xstatus.h" - -/************************** Constant Definitions *****************************/ - - -/**************************** Type Definitions *******************************/ - -/* xutil_memtest defines */ - -#define XUT_MEMTEST_INIT_VALUE 1 - -/** @name Memory subtests - * @{ - */ -/** - * See the detailed description of the subtests in the file description. - */ -#define XUT_ALLMEMTESTS 0 -#define XUT_INCREMENT 1 -#define XUT_WALKONES 2 -#define XUT_WALKZEROS 3 -#define XUT_INVERSEADDR 4 -#define XUT_FIXEDPATTERN 5 -#define XUT_MAXTEST XUT_FIXEDPATTERN -/* @} */ - -/***************** Macros (Inline Functions) Definitions *********************/ - - -/************************** Function Prototypes ******************************/ - -/* xutil_memtest prototypes */ - -int XUtil_MemoryTest32(u32 *Addr, u32 Words, u32 Pattern, u8 Subtest); -int XUtil_MemoryTest16(u16 *Addr, u32 Words, u16 Pattern, u8 Subtest); -int XUtil_MemoryTest8(u8 *Addr, u32 Words, u8 Pattern, u8 Subtest); - -#ifdef __cplusplus -} -#endif - -#endif /* end of protection macro */ -/** @} */ diff --git a/thirdparty/libxil/include/xilinx/xversion.h b/thirdparty/libxil/include/xilinx/xversion.h deleted file mode 100644 index 8dad9824c..000000000 --- a/thirdparty/libxil/include/xilinx/xversion.h +++ /dev/null @@ -1,111 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -/*****************************************************************************/ -/** -* @file xversion.h -* @addtogroup common_v1_00_a -* @{ -* -* This file contains the interface for the XVersion component. This -* component represents a version ID. It is encapsulated within a component -* so that it's type and implementation can change without affecting users of -* it. -* -* The version is formatted as X.YYZ where X = 0 - 9, Y = 00 - 99, Z = a - z -* X is the major revision, YY is the minor revision, and Z is the -* compatability revision. -* -* Packed versions are also utilized for the configuration ROM such that -* memory is minimized. A packed version consumes only 16 bits and is -* formatted as follows. -* -*
-* Revision                  Range       Bit Positions
-*
-* Major Revision            0 - 9       Bits 15 - 12
-* Minor Revision            0 - 99      Bits 11 - 5
-* Compatability Revision    a - z       Bits 4 - 0
-*
-* MODIFICATION HISTORY:
-*
-* Ver   Who    Date   Changes
-* ----- ---- -------- -------------------------------------------------------
-* 1.00a xd   11/03/04 Improved support for doxygen.
-* 
-* -******************************************************************************/ - -#ifndef XVERSION_H /* prevent circular inclusions */ -#define XVERSION_H /* by using protection macros */ - -#ifdef __cplusplus -extern "C" { -#endif - -/***************************** Include Files *********************************/ - -#include "xbasic_types.h" -#include "xstatus.h" - -/************************** Constant Definitions *****************************/ - - -/**************************** Type Definitions *******************************/ - -/* the following data type is used to hold a null terminated version string - * consisting of the following format, "X.YYX" - */ -typedef char XVersion[6]; - -/***************** Macros (Inline Functions) Definitions *********************/ - - -/************************** Function Prototypes ******************************/ - -void XVersion_UnPack(XVersion *InstancePtr, u16 PackedVersion); - -int XVersion_Pack(XVersion *InstancePtr, u16 *PackedVersion); - -int XVersion_IsEqual(XVersion *InstancePtr, XVersion *VersionPtr); - -void XVersion_ToString(XVersion *InstancePtr, char *StringPtr); - -int XVersion_FromString(XVersion *InstancePtr, char *StringPtr); - -void XVersion_Copy(XVersion *InstancePtr, XVersion *VersionPtr); - -#ifdef __cplusplus -} -#endif - -#endif /* end of protection macro */ -/** @} */ diff --git a/thirdparty/libxil/libxil.pc.in b/thirdparty/libxil/libxil.pc.in deleted file mode 100644 index 5f98b236a..000000000 --- a/thirdparty/libxil/libxil.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@CMAKE_INSTALL_PREFIX@ -exec_prefix=${prefix} -includedir=${prefix}/include -libdir=${exec_prefix}/lib - -Name: xil -Description: Xilinx standalone drivers -Version: 1.0.0 -Cflags: -I${includedir} -Libs: -L${libdir} -lxil \ No newline at end of file diff --git a/thirdparty/libxil/orig/README.md b/thirdparty/libxil/orig/README.md deleted file mode 100644 index 16edb5122..000000000 --- a/thirdparty/libxil/orig/README.md +++ /dev/null @@ -1 +0,0 @@ -Those drivers are taken from https://github.com/Xilinx/embeddedsw \ No newline at end of file diff --git a/thirdparty/libxil/orig/axidma_v9_0/data/axidma.mdd b/thirdparty/libxil/orig/axidma_v9_0/data/axidma.mdd deleted file mode 100644 index 773a39d3c..000000000 --- a/thirdparty/libxil/orig/axidma_v9_0/data/axidma.mdd +++ /dev/null @@ -1,43 +0,0 @@ -############################################################################### -# -# Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# Use of the Software is limited solely to applications: -# (a) running on a Xilinx device, or -# (b) that interact with a Xilinx device through a bus or interconnect. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -# Except as contained in this notice, the name of the Xilinx shall not be used -# in advertising or otherwise to promote the sale, use or other dealings in -# this Software without prior written authorization from Xilinx. -# -############################################################################## - -OPTION psf_version = 2.1; - -BEGIN driver axidma - - OPTION supported_peripherals = (axi_dma_v[3-9]_[0-9][0-9]_[a-z] axi_dma_v[3-9]_[0-9]); - OPTION driver_state = ACTIVE; - OPTION copyfiles = all; - OPTION VERSION = 9.0; - OPTION NAME = axidma; - -END driver diff --git a/thirdparty/libxil/orig/axidma_v9_0/data/axidma.tcl b/thirdparty/libxil/orig/axidma_v9_0/data/axidma.tcl deleted file mode 100644 index f0f806f76..000000000 --- a/thirdparty/libxil/orig/axidma_v9_0/data/axidma.tcl +++ /dev/null @@ -1,208 +0,0 @@ -############################################################################### -# -# Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# Use of the Software is limited solely to applications: -# (a) running on a Xilinx device, or -# (b) that interact with a Xilinx device through a bus or interconnect. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -# Except as contained in this notice, the name of the Xilinx shall not be used -# in advertising or otherwise to promote the sale, use or other dealings in -# this Software without prior written authorization from Xilinx. -# -# MODIFICATION HISTORY: -# Ver Who Date Changes -# -------- ------ -------- ---------------------------------------------------- -# 8.0 adk 12/10/13 Updated as per the New Tcl API's -############################################################################## - -#uses "xillib.tcl" - -set periph_ninstances 0 - -proc generate {drv_handle} { - ::hsi::utils::define_include_file $drv_handle "xparameters.h" "XAxiDma" "NUM_INSTANCES" "DEVICE_ID" "C_BASEADDR" "C_HIGHADDR" "C_SG_INCLUDE_STSCNTRL_STRM" "C_INCLUDE_MM2S_DRE" "C_INCLUDE_S2MM_DRE" "C_INCLUDE_MM2S" "C_INCLUDE_S2MM" "C_M_AXI_MM2S_DATA_WIDTH" "C_M_AXI_S2MM_DATA_WIDTH" "C_INCLUDE_SG" "C_ENABLE_MULTI_CHANNEL" "C_NUM_MM2S_CHANNELS" "C_NUM_S2MM_CHANNELS" "C_MM2S_BURST_SIZE" "C_S2MM_BURST_SIZE" "C_MICRO_DMA" "c_addr_width" - ::hsi::utils::define_canonical_xpars $drv_handle "xparameters.h" "AxiDma" "DEVICE_ID" "C_BASEADDR" "C_SG_INCLUDE_STSCNTRL_STRM" "C_INCLUDE_MM2S" "C_INCLUDE_MM2S_DRE" "C_M_AXI_MM2S_DATA_WIDTH" "C_INCLUDE_S2MM" "C_INCLUDE_S2MM_DRE" "C_M_AXI_S2MM_DATA_WIDTH" "C_INCLUDE_SG" "C_ENABLE_MULTI_CHANNEL" "C_NUM_MM2S_CHANNELS" "C_NUM_S2MM_CHANNELS" "C_MM2S_BURST_SIZE" "C_S2MM_BURST_SIZE" "C_MICRO_DMA" "c_addr_width" - ::hsi::utils::define_config_file $drv_handle "xaxidma_g.c" "XAxiDma" "DEVICE_ID" "C_BASEADDR" "C_SG_INCLUDE_STSCNTRL_STRM" "C_INCLUDE_MM2S" "C_INCLUDE_MM2S_DRE" "C_M_AXI_MM2S_DATA_WIDTH" "C_INCLUDE_S2MM" "C_INCLUDE_S2MM_DRE" "C_M_AXI_S2MM_DATA_WIDTH" "C_INCLUDE_SG" "C_NUM_MM2S_CHANNELS" "C_NUM_S2MM_CHANNELS" "C_MM2S_BURST_SIZE" "C_S2MM_BURST_SIZE" "C_MICRO_DMA" "c_addr_width" -} - -# -# Given a list of arguments, define them all in an include file. -# Handles mpd and mld parameters, as well as the special parameters NUM_INSTANCES, -# DEVICE_ID -# Will not work for a processor. -# - -proc xdefine_dma_include_file {drv_handle file_name drv_string args} { - # Open include file - set file_handle [xopen_include_file $file_name] - - # Get all peripherals connected to this driver - set periphs [xget_sw_iplist_for_driver $drv_handle] - - # Handle special cases - set arg "NUM_INSTANCES" - set posn [lsearch -exact $args $arg] - if {$posn > -1} { - puts $file_handle "/* Definitions for driver [string toupper [get_property NAME $drv_handle]] */" - # Define NUM_INSTANCES - puts $file_handle "#define [xget_dname $drv_string $arg] [llength $periphs]" - set args [lreplace $args $posn $posn] - } - # Check if it is a driver parameter - - lappend newargs - foreach arg $args { - set value [get_property CONFIG.$arg $drv_handle] - if {[llength $value] == 0} { - lappend newargs $arg - } else { - puts $file_handle "#define [xget_dname $drv_string $arg] [get_property CONFIG.$arg $drv_handle]" - } - } - set args $newargs - - # Print all parameters for all peripherals - set device_id 0 - foreach periph $periphs { - puts $file_handle "" - puts $file_handle "/* Definitions for peripheral [string toupper [get_property NAME $periph]] */" - foreach arg $args { - if {[string compare -nocase "DEVICE_ID" $arg] == 0} { - set value $device_id - incr device_id - } else { - set value [xget_param_value $periph $arg] - if {[string compare -nocase $arg "C_INCLUDE_SG"] == 0} { - if {[llength $value] == 0} { - set value 1 - } - } else { - if {[llength $value] == 0} { - set value 0 - } - } - if {[string compare -nocase $arg "C_MICRO_DMA"] == 0} { - if {[llength $value] == 0} { - set value 1 - } - } else { - if {[llength $value] == 0} { - set value 0 - } - } - } - - set value [xformat_addr_string $value $arg] - if {[string compare -nocase "HW_VER" $arg] == 0} { - puts $file_handle "#define [xget_name $periph $arg] \"$value\"" - } else { - puts $file_handle "#define [xget_name $periph $arg] $value" - } - } - puts $file_handle "" - } - puts $file_handle "\n/******************************************************************/\n" - close $file_handle -} - -#----------------------------------------------------------------------------- -# ::hsi::utils::define_canonical_xpars - Used to print out canonical defines for a driver. -# Given a list of arguments, define each as a canonical constant name, using -# the driver name, in an include file. -#----------------------------------------------------------------------------- -proc xdefine_axidma_canonical_xpars {drv_handle file_name drv_string args} { - # Open include file - set file_handle [xopen_include_file $file_name] - - # Get all the peripherals connected to this driver - set periphs [xget_sw_iplist_for_driver $drv_handle] - - # Get the names of all the peripherals connected to this driver - foreach periph $periphs { - set peripheral_name [string toupper [get_property NAME $periph]] - lappend peripherals $peripheral_name - } - - # Get possible canonical names for all the peripherals connected to this - # driver - set device_id 0 - foreach periph $periphs { - set canonical_name [string toupper [format "%s_%s" $drv_string $device_id]] - lappend canonicals $canonical_name - - # Create a list of IDs of the peripherals whose hardware instance name - # doesn't match the canonical name. These IDs can be used later to - # generate canonical definitions - if { [lsearch $peripherals $canonical_name] < 0 } { - lappend indices $device_id - } - incr device_id - } - - set i 0 - foreach periph $periphs { - set periph_name [string toupper [get_property NAME $periph]] - - # Generate canonical definitions only for the peripherals whose - # canonical name is not the same as hardware instance name - if { [lsearch $canonicals $periph_name] < 0 } { - puts $file_handle "/* Canonical definitions for peripheral $periph_name */" - set canonical_name [format "%s_%s" $drv_string [lindex $indices $i]] - - foreach arg $args { - set lvalue [xget_dname $canonical_name $arg] - # The commented out rvalue is the name of the instance-specific constant - # set rvalue [xget_name $periph $arg] - # The rvalue set below is the actual value of the parameter - set rvalue [xget_param_value $periph $arg] - - if {[string compare -nocase $arg "C_INCLUDE_SG"] == 0} { - if {[llength $rvalue] == 0} { - set rvalue 1 - } - } else { - if {[llength $rvalue] == 0} { - set rvalue 0 - } - } - if {[string compare -nocase $arg "C_MICRO_DMA"] == 0} { - if {[llength $rvalue] == 0} { - set rvalue 1 - } - } else { - if {[llength $rvalue] == 0} { - set rvalue 0 - } - } - set rvalue [xformat_addr_string $rvalue $arg] - - puts $file_handle "#define $lvalue $rvalue" - - } - puts $file_handle "" - incr i - } - } - - puts $file_handle "\n/******************************************************************/\n" - close $file_handle -} diff --git a/thirdparty/libxil/orig/axidma_v9_0/data/axidma_header.h b/thirdparty/libxil/orig/axidma_v9_0/data/axidma_header.h deleted file mode 100644 index fe4fab014..000000000 --- a/thirdparty/libxil/orig/axidma_v9_0/data/axidma_header.h +++ /dev/null @@ -1,41 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2005 - 2014 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ -#ifndef AXIDMA_HEADER_H /* prevent circular inclusions */ -#define AXIDMA_HEADER_H /* by using protection macros */ - -#include "xil_types.h" -#include "xil_assert.h" -#include "xstatus.h" - -int AxiDMASelfTestExample(u16 DeviceId); - -#endif diff --git a/thirdparty/libxil/orig/axidma_v9_0/data/axidma_tapp.tcl b/thirdparty/libxil/orig/axidma_v9_0/data/axidma_tapp.tcl deleted file mode 100644 index 865d9d319..000000000 --- a/thirdparty/libxil/orig/axidma_v9_0/data/axidma_tapp.tcl +++ /dev/null @@ -1,121 +0,0 @@ -############################################################################### -# -# Copyright (C) 2005 - 2014 Xilinx, Inc. All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# Use of the Software is limited solely to applications: -# (a) running on a Xilinx device, or -# (b) that interact with a Xilinx device through a bus or interconnect. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -# Except as contained in this notice, the name of the Xilinx shall not be used -# in advertising or otherwise to promote the sale, use or other dealings in -# this Software without prior written authorization from Xilinx. -# -############################################################################## -# Uses $XILINX_EDK/bin/lib/xillib_sw.tcl - -# ----------------------------------------------------------------- -# Software Project Types (swproj): -# 0 : MemoryTest - Calls basic memorytest routines from common driver dir -# 1 : PeripheralTest - Calls any existing polled_example and/or selftest -# ----------------------------------------------------------------- - -# ----------------------------------------------------------------- -# TCL Procedures: -# ----------------------------------------------------------------- - -proc gen_include_files {swproj mhsinst} { - if {$swproj == 0} { - return "" - } - if {$swproj == 1} { - set inc_file_lines {axidma_header.h} - return $inc_file_lines - } -} - -proc gen_src_files {swproj mhsinst} { - if {$swproj == 0} { - return "" - } - if {$swproj == 1} { - set inc_file_lines {examples/xaxidma_example_selftest.c data/axidma_header.h} - return $inc_file_lines - } -} - -proc gen_testfunc_def {swproj mhsinst} { - return "" -} - -proc gen_init_code {swproj mhsinst} { - return "" -} - -proc gen_testfunc_call {swproj mhsinst} { - - if {$swproj == 0} { - return "" - } - - set ipname [get_property NAME $mhsinst] - set deviceid [::hsi::utils::get_ip_param_name $mhsinst "DEVICE_ID"] - set stdout [get_property CONFIG.STDOUT [get_os]] - if { $stdout == "" || $stdout == "none" } { - set hasStdout 0 - } else { - set hasStdout 1 - } - - set testfunc_call "" - - if {${hasStdout} == 0} { - - append testfunc_call " - - { - int status; - - status = AxiDMASelfTestExample(${deviceid}); - - }" - } else { - - append testfunc_call " - - { - int status; - - - print(\"\\r\\n Running AxiDMASelfTestExample() for ${ipname}...\\r\\n\"); - - status = AxiDMASelfTestExample(${deviceid}); - - if (status == 0) { - print(\"AxiDMASelfTestExample PASSED\\r\\n\"); - } - else { - print(\"AxiDMASelfTestExample FAILED\\r\\n\"); - } - }" - } - - return $testfunc_call -} diff --git a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/HTML_custom.css b/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/HTML_custom.css deleted file mode 100644 index 26defe1a8..000000000 --- a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/HTML_custom.css +++ /dev/null @@ -1,1430 +0,0 @@ -/* The standard CSS for doxygen 1.8.5 */ - -body{ - background: none repeat scroll 0 0 #FFFFFF; - color: #51626F; - font-family: arial,sans-serif !important; - font-size: 75% !important; - font-weight: normal !important; - margin-left: 10px; - font: 400 12px/15px arial,sans-serif; -} -.contents, .textblock { -font: 400 12px/15px arial,sans-serif; -} -.textblock ul, .contents ul{ - margin: 5px 0; - padding: 0; -} -.textblockol { - margin:5px 15px; - padding:0; - list-style-image: none; -} -.textblock li, .contents li { - margin: 0 0 2px 15px; - padding: 0 0 2px 2px; -} - -/* For hiding RHS TOC -.toc{ -display:none; -}*/ -/* For hiding RHS TOC*/ - -For hiding Nav Bar -.navpath, #nav-path{ -display:none; -} -/* For hiding Nav Bar*/ -/* For hiding extra navrows */ -#navrow2, #navrow3, #navrow4, #navrow5 { -display:none; -} -/* @group Heading Levels */ - -.title { - font: 400 14px/28px arial,sans-serif; - font-size: 150%; - font-weight: bold; - margin: 9px 2px; - text-align: left; -} - -h2, h3 { - color: #E66A08 !important; - font-size: 1.2em !important; - line-height: 1.2em !important; - text-indent: 0 !important; -} -h4, h5{ - color: #E66A08 !important; - font-size: 1.2em !important; - line-height: 1.2em !important; -} -h5{ - font-size: 1.0em !important; - line-height: 1.0em !important; -} -h6{ - color: #E66A08 !important; - font-size: 1.0em !important; - line-height: 1.0em !important; -} -p { - padding-bottom: 0px !important; - font: 400 12px/15px arial,sans-serif; -} -li p { - padding-bottom: 0px !important; - margin: 0px; -} - -h1, h2.groupheader { - clear: both !important; - color: #627178 !important; - font-size: 1.4em !important; - font-weight: bold !important; - line-height: 28px !important; - margin-top: 0.6em !important; -} - -h1, h2, h3, h4, h5, h6 { - -webkit-transition: text-shadow 0.5s linear; - -moz-transition: text-shadow 0.5s linear; - -ms-transition: text-shadow 0.5s linear; - -o-transition: text-shadow 0.5s linear; - transition: text-shadow 0.5s linear; - margin-right: 15px; -} - -h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { - text-shadow: 0 0 15px cyan; -} - -dt { - font-weight: bold; -} - - -/*Hiding Tabs - Tushar -div.tabs -{ - visibility: hidden; -} */ - -div.multicol { - -moz-column-gap: 1em; - -webkit-column-gap: 1em; - -moz-column-count: 3; - -webkit-column-count: 3; -} - -p.startli, p.startdd, p.starttd { - margin-top: 2px; -} - -p.endli { - margin-bottom: 0px; -} - -p.enddd { - margin-bottom: 4px; -} - -p.endtd { - margin-bottom: 2px; -} - -/* @end */ - -caption { - font-weight: bold; -} - -span.legend { - font-size: 70%; - text-align: center; -} - -h3.version { - font-size: 90%; - text-align: center; -} - -div.qindex, div.navtab{ - background-color: #EBEFF6; - border: 1px solid #A3B4D7; - text-align: center; -} - -div.qindex, div.navpath { - width: 100%; - line-height: 140%; -} - -div.navtab { - margin-right: 15px; -} - -/* @group Link Styling */ - -a { - color: #017bba; - font-weight: normal; - text-decoration: none; - /*font: 400 12px/15px;*/ -} - -.contents a:visited { - color: #4665A2; -} - -a:hover { - text-decoration: underline; -} - -a.qindex { - font-weight: bold; -} - -a.qindexHL { - font-weight: bold; - background-color: #9CAFD4; - color: #ffffff; - border: 1px double #869DCA; -} - -.contents a.qindexHL:visited { - color: #ffffff; -} - -a.el { - font-weight: bold; -} - -a.elRef { -} - -a.code, a.code:visited, a.line, a.line:visited { - color: #4665A2; -} - -a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { - color: #4665A2; - /*font: 400 12px/15px;*/ -} - -/* @end */ - -dl.el { - margin-left: -1cm; -} - -pre.fragment { - border: 0px solid #C4CFE5; - background-color: #FFFFFF; - padding: 4px 6px; - margin: 4px 8px 4px 2px; - overflow: auto; - word-wrap: break-word; - font-size: 9pt; - line-height: 125%; - font-family: monospace, fixed; - font-size: 105%; -} - -div.fragment { - padding: 0px; - margin: 0px; - background-color: #FFFFFF; - border: 0px solid #C4CFE5; -} - -div.line { - font-family: monospace, fixed; - font-size: 13px; - min-height: 13px; - line-height: 1.0; - text-wrap: unrestricted; - white-space: -moz-pre-wrap; /* Moz */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - white-space: pre-wrap; /* CSS3 */ - word-wrap: break-word; /* IE 5.5+ */ - text-indent: -53px; - padding-left: 53px; - padding-bottom: 0px; - margin: 0px; - -webkit-transition-property: background-color, box-shadow; - -webkit-transition-duration: 0.5s; - -moz-transition-property: background-color, box-shadow; - -moz-transition-duration: 0.5s; - -ms-transition-property: background-color, box-shadow; - -ms-transition-duration: 0.5s; - -o-transition-property: background-color, box-shadow; - -o-transition-duration: 0.5s; - transition-property: background-color, box-shadow; - transition-duration: 0.5s; -} - -div.line.glow { - background-color: cyan; - box-shadow: 0 0 10px cyan; -} - - -span.lineno { - padding-right: 4px; - text-align: right; - border-right: 2px solid #0F0; - background-color: #E8E8E8; - white-space: pre; -} -span.lineno a { - background-color: #D8D8D8; -} - -span.lineno a:hover { - background-color: #C8C8C8; -} - -div.ah { - background-color: black; - font-weight: bold; - color: #ffffff; - margin-bottom: 3px; - margin-top: 3px; - padding: 0.2em; - border: solid thin #333; - border-radius: 0.5em; - -webkit-border-radius: .5em; - -moz-border-radius: .5em; - box-shadow: 2px 2px 3px #999; - -webkit-box-shadow: 2px 2px 3px #999; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; - background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); - background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); -} - -div.groupHeader { - margin-left: 16px; - margin-top: 12px; - font-weight: bold; -} - -div.groupText { - margin-left: 16px; - font-style: italic; -} - -body { - background-color: white; - margin: 0; -} - -div.contents { - margin-top: 10px; - margin-left: 12px; - margin-right: 8px; -} - -td.indexkey { - background-color: #EBEFF6; - font-weight: bold; - border: 1px solid #C4CFE5; - margin: 2px 0px 2px 0; - padding: 2px 10px; - white-space: nowrap; - vertical-align: top; -} - -td.indexvalue { - background-color: #EBEFF6; - border: 1px solid #C4CFE5; - padding: 2px 10px; - margin: 2px 0px; -} - -tr.memlist { - background-color: #EEF1F7; -} - -p.formulaDsp { - text-align: center; -} - -img.formulaDsp { - -} - -img.formulaInl { - vertical-align: middle; -} - -div.center { - text-align: center; - margin-top: 0px; - margin-bottom: 0px; - padding: 0px; -} - -div.center img { - border: 0px; -} - -address.footer { - text-align: right; - padding-right: 12px; -} - -img.footer { - border: 0px; - vertical-align: middle; -} - -/* @group Code Colorization */ - -span.keyword { - color: #008000 -} - -span.keywordtype { - color: #604020 -} - -span.keywordflow { - color: #e08000 -} - -span.comment { - color: #51626F -} - -span.preprocessor { - color: #806020 -} - -span.stringliteral { - color: #002080 -} - -span.charliteral { - color: #008080 -} - -span.vhdldigit { - color: #ff00ff -} - -span.vhdlchar { - color: #000000 -} - -span.vhdlkeyword { - color: #700070 -} - -span.vhdllogic { - color: #ff0000 -} - -blockquote { - background-color: #F7F8FB; - border-left: 2px solid #9CAFD4; - margin: 0 24px 0 4px; - padding: 0 12px 0 16px; -} - -/* @end */ - -/* -.search { - color: #003399; - font-weight: bold; -} - -form.search { - margin-bottom: 0px; - margin-top: 0px; -} - -input.search { - font-size: 75%; - color: #000080; - font-weight: normal; - background-color: #e8eef2; -} -*/ - -td.tiny { - font-size: 75%; -} - -.dirtab { - padding: 4px; - border-collapse: collapse; - border: 1px solid #A3B4D7; -} - -th.dirtab { - background: #EBEFF6; - font-weight: bold; -} - -hr { - height: 0px; - border: none; - border-top: 1px solid #4A6AAA; -} - -hr.footer { - height: 1px; -} - -/* @group Member Descriptions */ - -table.memberdecls { - border-spacing: 0px; - padding: 0px; -} - -.memberdecls td, .fieldtable tr { - -webkit-transition-property: background-color, box-shadow; - -webkit-transition-duration: 0.5s; - -moz-transition-property: background-color, box-shadow; - -moz-transition-duration: 0.5s; - -ms-transition-property: background-color, box-shadow; - -ms-transition-duration: 0.5s; - -o-transition-property: background-color, box-shadow; - -o-transition-duration: 0.5s; - transition-property: background-color, box-shadow; - transition-duration: 0.5s; -} - -.memberdecls td.glow, .fieldtable tr.glow { - background-color: cyan; - box-shadow: 0 0 15px cyan; -} - -.mdescLeft, .mdescRight, -.memItemLeft, .memItemRight, -.memTemplItemLeft, .memTemplItemRight, .memTemplParams { - background-color: #F9FAFC; - border: none; - margin: 4px; - padding: 1px 0 0 8px; -} - -.mdescLeft, .mdescRight { - padding: 0px 8px 4px 8px; - color: #555; -} - -.memSeparator { - border-bottom: 1px solid #DEE4F0; - line-height: 1px; - margin: 0px; - padding: 0px; -} - -.memItemLeft, .memTemplItemLeft { - white-space: nowrap; -} - -.memItemRight { - width: 100%; -} - -.memTemplParams { - color: #4665A2; - white-space: nowrap; - font-size: 80%; -} - -/* @end */ - -/* @group Member Details */ - -/* Styles for detailed member documentation */ - -.memtemplate { - font-size: 80%; - color: #4665A2; - font-weight: normal; - margin-left: 9px; -} - -.memnav { - background-color: #EBEFF6; - border: 1px solid #A3B4D7; - text-align: center; - margin: 2px; - margin-right: 15px; - padding: 2px; -} - -.mempage { - width: 100%; -} - -.memitem { - padding: 0; - margin-bottom: 10px; - margin-right: 5px; - -webkit-transition: box-shadow 0.5s linear; - -moz-transition: box-shadow 0.5s linear; - -ms-transition: box-shadow 0.5s linear; - -o-transition: box-shadow 0.5s linear; - transition: box-shadow 0.5s linear; - display: table !important; - width: 100%; -} - -.memitem.glow { - box-shadow: 0 0 15px cyan; -} - -.memname { - font-weight: bold; - margin-left: 6px; -} - -.memname td { - vertical-align: bottom; -} - -.memproto, dl.reflist dt { - border-top: 1px solid #A8B8D9; - border-left: 1px solid #A8B8D9; - border-right: 1px solid #A8B8D9; - padding: 6px 0px 6px 0px; - color: #E66A08 !important; - font-weight: bold; - text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); - background-image:url('nav_f.png'); - background-repeat:repeat-x; - background-color: #E2E8F2; - /* opera specific markup */ - box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - border-top-right-radius: 4px; - border-top-left-radius: 4px; - /* firefox specific markup */ - -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; - -moz-border-radius-topright: 4px; - -moz-border-radius-topleft: 4px; - /* webkit specific markup */ - -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - -webkit-border-top-right-radius: 4px; - -webkit-border-top-left-radius: 4px; - -} - -.memdoc, dl.reflist dd { - border-bottom: 1px solid #A8B8D9; - border-left: 1px solid #A8B8D9; - border-right: 1px solid #A8B8D9; - padding: 6px 10px 2px 10px; - background-color: #FBFCFD; - border-top-width: 0; - background-image:url('nav_g.png'); - background-repeat:repeat-x; - background-color: #FFFFFF; - /* opera specific markup */ - border-bottom-left-radius: 4px; - border-bottom-right-radius: 4px; - box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - /* firefox specific markup */ - -moz-border-radius-bottomleft: 4px; - -moz-border-radius-bottomright: 4px; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; - /* webkit specific markup */ - -webkit-border-bottom-left-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); -} - -dl.reflist dt { - padding: 5px; -} - -dl.reflist dd { - margin: 0px 0px 10px 0px; - padding: 5px; -} - -.paramkey { - text-align: right; -} - -.paramtype { - white-space: nowrap; -} - -.paramname { - color: #602020; - white-space: nowrap; -} -.paramname em { - font-style: normal; -} -.paramname code { - line-height: 14px; -} - -.params, .retval, .exception, .tparams { - margin-left: 0px; - padding-left: 0px; - font: 400 12px/15px arial,sans-serif; -} - -.params .paramname, .retval .paramname { - font-weight: bold; - vertical-align: top; -} - -.params .paramtype { - font-style: italic; - vertical-align: top; -} - -.params .paramdir { - font-family: "courier new",courier,monospace; - vertical-align: top; -} - -table.mlabels { - border-spacing: 0px; -} - -td.mlabels-left { - width: 100%; - padding: 0px; -} - -td.mlabels-right { - vertical-align: bottom; - padding: 0px; - white-space: nowrap; -} - -span.mlabels { - margin-left: 8px; -} - -span.mlabel { - background-color: #728DC1; - border-top:1px solid #5373B4; - border-left:1px solid #5373B4; - border-right:1px solid #C4CFE5; - border-bottom:1px solid #C4CFE5; - text-shadow: none; - color: white; - margin-right: 4px; - padding: 2px 3px; - border-radius: 3px; - font-size: 7pt; - white-space: nowrap; - vertical-align: middle; -} - - - -/* @end */ - -/* these are for tree view when not used as main index */ - -div.directory { - margin: 10px 0px; - border-top: 1px solid #A8B8D9; - border-bottom: 1px solid #A8B8D9; - width: 100%; -} - -.directory table { - border-collapse:collapse; -} - -.directory td { - margin: 0px; - padding: 0px; - vertical-align: top; -} - -.directory td.entry { - white-space: nowrap; - padding-right: 6px; - padding-top: 3px; -} - -.directory td.entry a { - outline:none; -} - -.directory td.entry a img { - border: none; -} - -.directory td.desc { - width: 100%; - padding-left: 6px; - padding-right: 6px; - padding-top: 3px; - border-left: 1px solid rgba(0,0,0,0.05); -} - -.directory tr.even { - padding-left: 6px; - background-color: #F7F8FB; -} - -.directory img { - vertical-align: -30%; -} - -.directory .levels { - white-space: nowrap; - width: 100%; - text-align: right; - font-size: 9pt; -} - -.directory .levels span { - cursor: pointer; - padding-left: 2px; - padding-right: 2px; - color: #3D578C; -} - -div.dynheader { - margin-top: 8px; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -address { - font-style: normal; - color: #2A3D61; -} - -table.doxtable { - border-collapse:collapse; - margin-top: 4px; - margin-bottom: 4px; - font: 400 12px/15px arial,sans-serif; -} - -table.doxtable td, table.doxtable th { - border: 1px solid #2D4068; - padding: 3px 7px 2px; -} - -table.doxtable th { - background-color: #CCCCCC; - color: #51626F; - font-size: 110%; - padding-bottom: 4px; - padding-top: 5px; -} -table.fieldtable { - /*width: 100%;*/ - margin-bottom: 10px; - border: 1px solid #A8B8D9; - border-spacing: 0px; - -moz-border-radius: 4px; - -webkit-border-radius: 4px; - border-radius: 4px; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; - -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); - box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); -} - -.fieldtable td, .fieldtable th { - padding: 3px 7px 2px; -} - -.fieldtable td.fieldtype, .fieldtable td.fieldname { - white-space: nowrap; - border-right: 1px solid #A8B8D9; - border-bottom: 1px solid #A8B8D9; - vertical-align: top; -} - -.fieldtable td.fieldname { - padding-top: 3px; -} - -.fieldtable td.fielddoc { - border-bottom: 1px solid #A8B8D9; - /*width: 100%;*/ -} - -.fieldtable td.fielddoc p:first-child { - margin-top: 0px; -} - -.fieldtable td.fielddoc p:last-child { - margin-bottom: 2px; -} - -.fieldtable tr:last-child td { - border-bottom: none; -} - -.fieldtable th { - background-image:url('nav_f.png'); - background-repeat:repeat-x; - background-color: #E2E8F2; - font-size: 90%; - color: #253555; - padding-bottom: 4px; - padding-top: 5px; - text-align:left; - -moz-border-radius-topleft: 4px; - -moz-border-radius-topright: 4px; - -webkit-border-top-left-radius: 4px; - -webkit-border-top-right-radius: 4px; - border-top-left-radius: 4px; - border-top-right-radius: 4px; - border-bottom: 1px solid #A8B8D9; -} - - -.tabsearch { - top: 5px; - left: 10px; - height: 36px; - background-image: url('tab_b.png'); - z-index: 101; - overflow: hidden; - font-size: 13px; -} - -.navpath ul -{ - font-size: 11px; - background-image:url('tab_b.png'); - background-repeat:repeat-x; - background-position: 0 -5px; - height:30px; - line-height:30px; - color:#8AA0CC; - border:solid 1px #C2CDE4; - overflow:hidden; - margin:0px; - padding:0px; -} - -.navpath li -{ - list-style-type:none; - float:left; - padding-left:10px; - padding-right:15px; - background-image:url('bc_s.png'); - background-repeat:no-repeat; - background-position:right; - color:#364D7C; -} - -.navpath li.navelem a -{ - height:32px; - display:block; - text-decoration: none; - outline: none; - color: #283A5D; - font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; - text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); - text-decoration: none; -} - -.navpath li.navelem a:hover -{ - color:#6884BD; -} - -.navpath li.footer -{ - list-style-type:none; - float:right; - padding-left:10px; - padding-right:15px; - background-image:none; - background-repeat:no-repeat; - background-position:right; - color:#364D7C; - font-size: 8pt; -} - - -div.summary -{ - float: right; - font-size: 8pt; - padding-right: 5px; - width: 50%; - text-align: right; -} - -div.summary a -{ - white-space: nowrap; -} - -div.ingroups -{ - font-size: 8pt; - width: 50%; - text-align: left; -} - -div.ingroups a -{ - white-space: nowrap; -} - -div.header -{ - background-image:url(''); - background-repeat:repeat-x; - background-color: #FFFFFF; - margin: 0px; - border-bottom: 0px solid #C4CFE5; -} - -div.headertitle -{ - padding: 5px 5px 5px 10px; -} - -dl -{ - padding: 0 0 0 10px; - font: 400 12px/15px arial,sans-serif; -} - -/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ -dl.section -{ - margin-left: 0px; - padding-left: 0px; -} - -dl.note -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #D0C000; -} - -dl.warning, dl.attention -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #FF0000; -} - -dl.pre, dl.post, dl.invariant -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #00D000; -} - -dl.deprecated -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #505050; -} - -dl.todo -{ - margin-left:-7px; - padding-left: 12px; - border-left:4px solid; - border-color: #00C0E0; -} - -dl.test -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #3030E0; -} - -dl.bug -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #C08050; -} - -dl.section dd { - margin-bottom: 6px; -} - - -#projectlogo -{ - text-align: center; - vertical-align: bottom; - border-collapse: separate; - padding: 12px; - -} - -#projectlogo img -{ - border: 0px none; -} - -#projectname -{ - font: 300% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 5px 0px; - text-align: right; - width: 100%; -} - -#projectbrief -{ - font: 120% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 5px; - text-align: left; - width: 100%; -} - -#projectnumber -{ - font: 50% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 0px; -} - -#titlearea -{ - padding: 0px; - margin: 0px; - width: 100%; - border-bottom: 11px solid #5373B4; -} - -.image -{ - text-align: left; -} - -.dotgraph -{ - text-align: center; -} - -.mscgraph -{ - text-align: center; -} - -.caption -{ - font-weight: bold; -} - -div.zoom -{ - border: 1px solid #90A5CE; -} - -dl.citelist { - margin-bottom:50px; -} - -dl.citelist dt { - color:#334975; - float:left; - font-weight:bold; - margin-right:10px; - padding:5px; -} - -dl.citelist dd { - margin:2px 0; - padding:5px 0; -} - -div.toc { - padding: 14px 25px; - background-color: #F4F6FA; - border: 1px solid #D8DFEE; - border-radius: 7px 7px 7px 7px; - float: right; - height: auto; - margin: 0 20px 10px 10px; - width: 200px; -} - -div.toc li { - background: url("bdwn.png") no-repeat scroll 0 5px transparent; - font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; - margin-top: 5px; - padding-left: 10px; - padding-top: 2px; -} - -div.toc h3 { - font: bold 12px/1.2 Arial,FreeSans,sans-serif; - color: #4665A2; - border-bottom: 0 none; - margin: 0; -} - -div.toc ul { - list-style: none outside none; - border: medium none; - padding: 0px; -} - -div.toc li.level1 { - margin-left: 0px; -} - -div.toc li.level2 { - margin-left: 15px; -} - -div.toc li.level3 { - margin-left: 30px; -} - -div.toc li.level4 { - margin-left: 45px; -} - -.inherit_header { - font-weight: bold; - color: gray; - cursor: pointer; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.inherit_header td { - padding: 6px 0px 2px 5px; -} - -.inherit { - display: none; -} - -tr.heading h2 { - margin-top: 12px; - margin-bottom: 4px; -} - -/* tooltip related style info */ - -.ttc { - position: absolute; - display: none; -} - -#powerTip { - cursor: default; - white-space: nowrap; - background-color: white; - border: 1px solid gray; - border-radius: 4px 4px 4px 4px; - box-shadow: 1px 1px 7px gray; - display: none; - font-size: smaller; - max-width: 80%; - opacity: 0.9; - padding: 1ex 1em 1em; - position: absolute; - z-index: 2147483647; -} - -#powerTip div.ttdoc { - color: grey; - font-style: italic; -} - -#powerTip div.ttname a { - font-weight: bold; -} - -#powerTip div.ttname { - font-weight: bold; -} - -#powerTip div.ttdeci { - color: #006318; -} - -#powerTip div { - margin: 0px; - padding: 0px; - font: 12px/16px arial,sans-serif; -} - -#powerTip:before, #powerTip:after { - content: ""; - position: absolute; - margin: 0px; -} - -#powerTip.n:after, #powerTip.n:before, -#powerTip.s:after, #powerTip.s:before, -#powerTip.w:after, #powerTip.w:before, -#powerTip.e:after, #powerTip.e:before, -#powerTip.ne:after, #powerTip.ne:before, -#powerTip.se:after, #powerTip.se:before, -#powerTip.nw:after, #powerTip.nw:before, -#powerTip.sw:after, #powerTip.sw:before { - border: solid transparent; - content: " "; - height: 0; - width: 0; - position: absolute; -} - -#powerTip.n:after, #powerTip.s:after, -#powerTip.w:after, #powerTip.e:after, -#powerTip.nw:after, #powerTip.ne:after, -#powerTip.sw:after, #powerTip.se:after { - border-color: rgba(255, 255, 255, 0); -} - -#powerTip.n:before, #powerTip.s:before, -#powerTip.w:before, #powerTip.e:before, -#powerTip.nw:before, #powerTip.ne:before, -#powerTip.sw:before, #powerTip.se:before { - border-color: rgba(128, 128, 128, 0); -} - -#powerTip.n:after, #powerTip.n:before, -#powerTip.ne:after, #powerTip.ne:before, -#powerTip.nw:after, #powerTip.nw:before { - top: 100%; -} - -#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { - border-top-color: #ffffff; - border-width: 10px; - margin: 0px -10px; -} -#powerTip.n:before { - border-top-color: #808080; - border-width: 11px; - margin: 0px -11px; -} -#powerTip.n:after, #powerTip.n:before { - left: 50%; -} - -#powerTip.nw:after, #powerTip.nw:before { - right: 14px; -} - -#powerTip.ne:after, #powerTip.ne:before { - left: 14px; -} - -#powerTip.s:after, #powerTip.s:before, -#powerTip.se:after, #powerTip.se:before, -#powerTip.sw:after, #powerTip.sw:before { - bottom: 100%; -} - -#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { - border-bottom-color: #ffffff; - border-width: 10px; - margin: 0px -10px; -} - -#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { - border-bottom-color: #808080; - border-width: 11px; - margin: 0px -11px; -} - -#powerTip.s:after, #powerTip.s:before { - left: 50%; -} - -#powerTip.sw:after, #powerTip.sw:before { - right: 14px; -} - -#powerTip.se:after, #powerTip.se:before { - left: 14px; -} - -#powerTip.e:after, #powerTip.e:before { - left: 100%; -} -#powerTip.e:after { - border-left-color: #ffffff; - border-width: 10px; - top: 50%; - margin-top: -10px; -} -#powerTip.e:before { - border-left-color: #808080; - border-width: 11px; - top: 50%; - margin-top: -11px; -} - -#powerTip.w:after, #powerTip.w:before { - right: 100%; -} -#powerTip.w:after { - border-right-color: #ffffff; - border-width: 10px; - top: 50%; - margin-top: -10px; -} -#powerTip.w:before { - border-right-color: #808080; - border-width: 11px; - top: 50%; - margin-top: -11px; -} - -@media print -{ - #top { display: none; } - #side-nav { display: none; } - #nav-path { display: none; } - body { overflow:visible; } - h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } - .summary { display: none; } - .memitem { page-break-inside: avoid; } - #doc-content - { - margin-left:0 !important; - height:auto !important; - width:auto !important; - overflow:inherit; - display:inline; - } -} - diff --git a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/annotated.html b/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/annotated.html deleted file mode 100644 index 7c33a3a71..000000000 --- a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/annotated.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - -axidma_v9_0: Data Structures - - - - - - - -
-
-
$projectname @@ -47,9 +50,9 @@ $(document).ready(function(){
$searchbox
- - - - - - -
-
axidma_v9_0 -
-
Xilinx SDK Drivers API Documentation
-
- - - - - - -
-
-
Data Structures
-
-
-
Here are the data structures with brief descriptions:
- - - - -
 CXAxiDmaThe XAxiDma driver instance data
 CXAxiDma_BdRingContainer structure for descriptor storage control
 CXAxiDma_ConfigThe configuration structure for AXI DMA engine
-
-
- - - diff --git a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/classes.html b/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/classes.html deleted file mode 100644 index 06bd550cc..000000000 --- a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/classes.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - -axidma_v9_0: Data Structure Index - - - - - - - -
-
- - - - - - - -
-
axidma_v9_0 -
-
Xilinx SDK Drivers API Documentation
-
-
- - - - -
-
-
-
Data Structure Index
-
-
- - - - - - -
  X  
-
XAxiDma_BdRing   XAxiDma_Config   
XAxiDma   
- -
- - - diff --git a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/doc.png b/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/doc.png deleted file mode 100644 index 17edabff9..000000000 Binary files a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/doc.png and /dev/null differ diff --git a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/dynsections.js b/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/dynsections.js deleted file mode 100644 index 85e183690..000000000 --- a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/dynsections.js +++ /dev/null @@ -1,97 +0,0 @@ -function toggleVisibility(linkObj) -{ - var base = $(linkObj).attr('id'); - var summary = $('#'+base+'-summary'); - var content = $('#'+base+'-content'); - var trigger = $('#'+base+'-trigger'); - var src=$(trigger).attr('src'); - if (content.is(':visible')===true) { - content.hide(); - summary.show(); - $(linkObj).addClass('closed').removeClass('opened'); - $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); - } else { - content.show(); - summary.hide(); - $(linkObj).removeClass('closed').addClass('opened'); - $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); - } - return false; -} - -function updateStripes() -{ - $('table.directory tr'). - removeClass('even').filter(':visible:even').addClass('even'); -} - -function toggleLevel(level) -{ - $('table.directory tr').each(function() { - var l = this.id.split('_').length-1; - var i = $('#img'+this.id.substring(3)); - var a = $('#arr'+this.id.substring(3)); - if (l - - - - - -axidma_v9_0: File List - - - - - - - -
-
- - - - - - - -
-
axidma_v9_0 -
-
Xilinx SDK Drivers API Documentation
-
-
- - - -
-
-
-
File List
-
-
-
Here is a list of all documented files with brief descriptions:
-
- - - diff --git a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/functions.html b/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/functions.html deleted file mode 100644 index 0bd7ad51e..000000000 --- a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/functions.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - -axidma_v9_0: Data Fields - - - - - - - -
-
- - - - - - - -
-
axidma_v9_0 -
-
Xilinx SDK Drivers API Documentation
-
-
- - - - - -
-
-
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
-
- - - diff --git a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/functions_vars.html b/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/functions_vars.html deleted file mode 100644 index ea2952237..000000000 --- a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/functions_vars.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - -axidma_v9_0: Data Fields - Variables - - - - - - - -
-
- - - - - - - -
-
axidma_v9_0 -
-
Xilinx SDK Drivers API Documentation
-
-
- - - - - -
-
-
- - - diff --git a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/globals.html b/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/globals.html deleted file mode 100644 index 10e1f1c51..000000000 --- a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/globals.html +++ /dev/null @@ -1,558 +0,0 @@ - - - - - - -axidma_v9_0: APIs - - - - - - - -
-
- - - - - - - -
-
axidma_v9_0 -
-
Xilinx SDK Drivers API Documentation
-
-
- - - - - -
-
-
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
- -

- x -

-
- - - diff --git a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/globals_defs.html b/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/globals_defs.html deleted file mode 100644 index dc4b4eaec..000000000 --- a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/globals_defs.html +++ /dev/null @@ -1,456 +0,0 @@ - - - - - - -axidma_v9_0: APIs - - - - - - - -
-
- - - - - - - -
-
axidma_v9_0 -
-
Xilinx SDK Drivers API Documentation
-
-
- - - - - -
-
-  - -

- x -

-
- - - diff --git a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/globals_func.html b/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/globals_func.html deleted file mode 100644 index 7e0916d17..000000000 --- a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/globals_func.html +++ /dev/null @@ -1,162 +0,0 @@ - - - - - - -axidma_v9_0: APIs - - - - - - - -
-
- - - - - - - -
-
axidma_v9_0 -
-
Xilinx SDK Drivers API Documentation
-
-
- - - - - -
-
-  - -

- x -

-
- - - diff --git a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/globals_type.html b/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/globals_type.html deleted file mode 100644 index b55476cd0..000000000 --- a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/globals_type.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - -axidma_v9_0: APIs - - - - - - - -
-
- - - - - - - -
-
axidma_v9_0 -
-
Xilinx SDK Drivers API Documentation
-
-
- - - - -
-
-
- - - diff --git a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/group__axidma__v9__0.html b/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/group__axidma__v9__0.html deleted file mode 100644 index a8d41e072..000000000 --- a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/group__axidma__v9__0.html +++ /dev/null @@ -1,5350 +0,0 @@ - - - - - - -axidma_v9_0: Axidma_v9_0 - - - - - - - -
-
- - - - - - - -
-
axidma_v9_0 -
-
Xilinx SDK Drivers API Documentation
-
-
- - - -
-
- -
-
Axidma_v9_0
-
-
- - - - - - - - -

-Data Structures

struct  XAxiDma
 
struct  XAxiDma_Config
 
struct  XAxiDma_BdRing
 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Macros

#define XAxiDma_GetTxRing(InstancePtr)   (&((InstancePtr)->TxBdRing))
 
#define XAxiDma_GetRxRing(InstancePtr)   (&((InstancePtr)->RxBdRing[0]))
 
#define XAxiDma_GetRxIndexRing(InstancePtr, RingIndex)   (&((InstancePtr)->RxBdRing[RingIndex]))
 
#define XAxiDma_HasSg(InstancePtr)   ((InstancePtr)->HasSg) ? TRUE : FALSE
 
#define XAxiDma_IntrEnable(InstancePtr, Mask, Direction)
 
#define XAxiDma_IntrGetEnabled(InstancePtr, Direction)
 
#define XAxiDma_IntrDisable(InstancePtr, Mask, Direction)
 
#define XAxiDma_IntrGetIrq(InstancePtr, Direction)
 
#define XAxiDma_IntrAckIrq(InstancePtr, Mask, Direction)
 
#define XAxiDma_BdRead(BaseAddress, Offset)   (*(u32 *)((UINTPTR)((void *)(BaseAddress)) + (u32)(Offset)))
 
#define XAxiDma_BdWrite(BaseAddress, Offset, Data)   (*(u32 *)((UINTPTR)(void *)(BaseAddress) + (u32)(Offset))) = (u32)(Data)
 
#define XAxiDma_BdClear(BdPtr)
 
#define XAxiDma_BdGetCtrl(BdPtr)
 
#define XAxiDma_BdGetSts(BdPtr)
 
#define XAxiDma_BdGetLength(BdPtr, LengthMask)
 
#define XAxiDma_BdSetId(BdPtr, Id)    (XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_ID_OFFSET, (u32)(Id)))
 
#define XAxiDma_BdGetId(BdPtr)   (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_ID_OFFSET))
 
#define XAxiDma_BdGetBufAddr(BdPtr)    (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_BUFA_OFFSET))
 
#define XAxiDma_BdHwCompleted(BdPtr)
 
#define XAxiDma_BdGetActualLength(BdPtr, LengthMask)
 
#define XAxiDma_BdSetTId(BdPtr, TId)
 
#define XAxiDma_BdGetTId(BdPtr)
 
#define XAxiDma_BdSetTDest(BdPtr, TDest)
 
#define XAxiDma_BdGetTDest(BdPtr)
 
#define XAxiDma_BdSetTUser(BdPtr, TUser)
 
#define XAxiDma_BdGetTUser(BdPtr)
 
#define XAxiDma_BdSetARCache(BdPtr, ARCache)
 
#define XAxiDma_BdGetARCache(BdPtr)
 
#define XAxiDma_BdSetARUser(BdPtr, ARUser)
 
#define XAxiDma_BdGetARUser(BdPtr)
 
#define XAxiDma_BdSetStride(BdPtr, Stride)
 
#define XAxiDma_BdGetStride(BdPtr)
 
#define XAxiDma_BdSetVSize(BdPtr, VSize)
 
#define XAxiDma_BdGetVSize(BdPtr)
 
#define XAxiDma_BdRingCntCalc(Alignment, Bytes)    (uint32_t)((Bytes)/((sizeof(XAxiDma_Bd)+((Alignment)-1))&~((Alignment)-1)))
 
#define XAxiDma_BdRingMemCalc(Alignment, NumBd)   (int)((sizeof(XAxiDma_Bd)+((Alignment)-1)) & ~((Alignment)-1))*(NumBd)
 
#define XAxiDma_BdRingGetCnt(RingPtr)   ((RingPtr)->AllCnt)
 
#define XAxiDma_BdRingGetFreeCnt(RingPtr)   ((RingPtr)->FreeCnt)
 
#define XAxiDma_BdRingSnapShotCurrBd(RingPtr)
 
#define XAxiDma_BdRingGetCurrBd(RingPtr)
 
#define XAxiDma_BdRingNext(RingPtr, BdPtr)
 
#define XAxiDma_BdRingPrev(RingPtr, BdPtr)
 
#define XAxiDma_BdRingGetSr(RingPtr)   XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET)
 
#define XAxiDma_BdRingGetError(RingPtr)
 
#define XAxiDma_BdRingHwIsStarted(RingPtr)
 
#define XAxiDma_BdRingBusy(RingPtr)
 
#define XAxiDma_BdRingIntEnable(RingPtr, Mask)
 
#define XAxiDma_BdRingIntGetEnabled(RingPtr)
 
#define XAxiDma_BdRingIntDisable(RingPtr, Mask)
 
#define XAxiDma_BdRingGetIrq(RingPtr)
 
#define XAxiDma_BdRingAckIrq(RingPtr, Mask)
 
- - - -

-Typedefs

typedef struct XAxiDma XAxiDma
 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Functions

int XAxiDma_CfgInitialize (XAxiDma *InstancePtr, XAxiDma_Config *Config)
 
void XAxiDma_Reset (XAxiDma *InstancePtr)
 
int XAxiDma_ResetIsDone (XAxiDma *InstancePtr)
 
int XAxiDma_Pause (XAxiDma *InstancePtr)
 
int XAxiDma_Resume (XAxiDma *InstancePtr)
 
u32 XAxiDma_Busy (XAxiDma *InstancePtr, int Direction)
 
int XAxiDma_SelectKeyHole (XAxiDma *InstancePtr, int Direction, int Select)
 
int XAxiDma_SelectCyclicMode (XAxiDma *InstancePtr, int Direction, int Select)
 
u32 XAxiDma_SimpleTransfer (XAxiDma *InstancePtr, UINTPTR BuffAddr, u32 Length, int Direction)
 
XAxiDma_ConfigXAxiDma_LookupConfig (u32 DeviceId)
 
int XAxiDma_Selftest (XAxiDma *InstancePtr)
 
int XAxiDma_BdSetLength (XAxiDma_Bd *BdPtr, u32 LenBytes, u32 LengthMask)
 
u32 XAxiDma_BdSetBufAddr (XAxiDma_Bd *BdPtr, UINTPTR Addr)
 
u32 XAxiDma_BdSetBufAddrMicroMode (XAxiDma_Bd *BdPtr, UINTPTR Addr)
 
int XAxiDma_BdSetAppWord (XAxiDma_Bd *BdPtr, int Offset, u32 Word)
 
u32 XAxiDma_BdGetAppWord (XAxiDma_Bd *BdPtr, int Offset, int *Valid)
 
void XAxiDma_BdSetCtrl (XAxiDma_Bd *BdPtr, u32 Data)
 
void XAxiDma_DumpBd (XAxiDma_Bd *BdPtr)
 
int XAxiDma_UpdateBdRingCDesc (XAxiDma_BdRing *RingPtr)
 
u32 XAxiDma_BdRingCreate (XAxiDma_BdRing *RingPtr, UINTPTR PhysAddr, UINTPTR VirtAddr, u32 Alignment, int BdCount)
 
int XAxiDma_BdRingClone (XAxiDma_BdRing *RingPtr, XAxiDma_Bd *SrcBdPtr)
 
int XAxiDma_StartBdRingHw (XAxiDma_BdRing *RingPtr)
 
int XAxiDma_BdRingStart (XAxiDma_BdRing *RingPtr)
 
int XAxiDma_BdRingSetCoalesce (XAxiDma_BdRing *RingPtr, u32 Counter, u32 Timer)
 
void XAxiDma_BdRingGetCoalesce (XAxiDma_BdRing *RingPtr, u32 *CounterPtr, u32 *TimerPtr)
 
int XAxiDma_BdRingAlloc (XAxiDma_BdRing *RingPtr, int NumBd, XAxiDma_Bd **BdSetPtr)
 
int XAxiDma_BdRingUnAlloc (XAxiDma_BdRing *RingPtr, int NumBd, XAxiDma_Bd *BdSetPtr)
 
int XAxiDma_BdRingToHw (XAxiDma_BdRing *RingPtr, int NumBd, XAxiDma_Bd *BdSetPtr)
 
int XAxiDma_BdRingFromHw (XAxiDma_BdRing *RingPtr, int BdLimit, XAxiDma_Bd **BdSetPtr)
 
int XAxiDma_BdRingFree (XAxiDma_BdRing *RingPtr, int NumBd, XAxiDma_Bd *BdSetPtr)
 
int XAxiDma_BdRingCheck (XAxiDma_BdRing *RingPtr)
 
void XAxiDma_BdRingDumpRegs (XAxiDma_BdRing *RingPtr)
 
- - - - -

-Device registers

Register sets on TX and RX channels are identical

-
#define XAXIDMA_RX_CDESC0_OFFSET   0x00000040
 
- - - - - -

-Bitmasks and shift values for XAXIDMA_BD_STRIDE_VSIZE_OFFSET register

#define XAxiDma_ReadReg(BaseAddress, RegOffset)    XAxiDma_In32((BaseAddress) + (RegOffset))
 
#define XAxiDma_WriteReg(BaseAddress, RegOffset, Data)    XAxiDma_Out32((BaseAddress) + (RegOffset), (Data))
 
-

Macro Definition Documentation

- -
-
- - - - -
#define XAXIDMA_BD_ADDRLEN_OFFSET   0x40
-
- -

#include <xaxidma_hw.h>

- -

Check for BD Addr.

- -

Referenced by XAxiDma_BdRingCreate(), XAxiDma_BdSetBufAddr(), and XAxiDma_BdSetBufAddrMicroMode().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_BUFA_MSB_OFFSET   0x0C
-
- -

#include <xaxidma_hw.h>

- -

Buffer address.

- -

Referenced by XAxiDma_BdSetBufAddr(), and XAxiDma_BdSetBufAddrMicroMode().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_BUFA_OFFSET   0x08
-
- -

#include <xaxidma_hw.h>

- -

Buffer address.

- -

Referenced by XAxiDma_BdSetBufAddr(), XAxiDma_BdSetBufAddrMicroMode(), and XAxiDma_DumpBd().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_BYTES_TO_CLEAR   48
-
- -

#include <xaxidma_hw.h>

- -

BD specific bytes to be cleared.

- -

Referenced by XAxiDma_BdRingClone().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_CTRL_ALL_MASK   0x0C000000
-
- -

#include <xaxidma_hw.h>

- -

All control bits.

- -

Referenced by XAxiDma_BdSetCtrl().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_CTRL_LEN_OFFSET   0x18
-
- -

#include <xaxidma_hw.h>

- -

Control/buffer length.

- -

Referenced by XAxiDma_BdRingFromHw(), XAxiDma_BdRingToHw(), XAxiDma_BdSetCtrl(), XAxiDma_BdSetLength(), and XAxiDma_DumpBd().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_CTRL_TXEOF_MASK   0x04000000
-
- -

#include <xaxidma_hw.h>

- -

Last tx packet.

- -

Referenced by XAxiDma_BdRingFromHw(), and XAxiDma_BdRingToHw().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_CTRL_TXSOF_MASK   0x08000000
-
- -

#include <xaxidma_hw.h>

- -

First tx packet.

- -

Referenced by XAxiDma_BdRingToHw().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_HAS_DRE_MASK   0xF00
-
- -

#include <xaxidma_hw.h>

- -

Whether has DRE mask.

- -

Referenced by XAxiDma_BdSetBufAddr().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_HAS_DRE_OFFSET   0x3C
-
- -

#include <xaxidma_hw.h>

- -

Whether has DRE.

- -

Referenced by XAxiDma_BdRingCreate(), XAxiDma_BdSetBufAddr(), and XAxiDma_DumpBd().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_HAS_DRE_SHIFT   8
-
- -

#include <xaxidma_hw.h>

- -

Whether has DRE shift.

- -

Referenced by XAxiDma_BdRingCreate().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_HAS_STSCNTRL_OFFSET   0x38
-
- -

#include <xaxidma_hw.h>

- -

Whether has stscntrl strm.

- -

Referenced by XAxiDma_BdGetAppWord(), XAxiDma_BdRingCreate(), XAxiDma_BdSetAppWord(), and XAxiDma_DumpBd().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_HW_NUM_BYTES   52
-
- -

#include <xaxidma_hw.h>

- -

Number of bytes hw used.

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_ID_OFFSET   0x34
-
- -

#include <xaxidma_hw.h>

- -

Sw ID.

- -

Referenced by XAxiDma_DumpBd().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_MCCTL_OFFSET   0x10
-
- -

#include <xaxidma_hw.h>

- -

Multichannel Control Fields.

- -

Referenced by XAxiDma_DumpBd().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_MINIMUM_ALIGNMENT   0x40
-
- -

#include <xaxidma_hw.h>

- -

Minimum byte alignment requirement for descriptors to satisfy both hardware/software needs.

- -

Referenced by XAxiDma_BdRingCreate().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_NDESC_MSB_OFFSET   0x04
-
- -

#include <xaxidma_hw.h>

- -

Next descriptor pointer.

- -

Referenced by XAxiDma_BdRingCreate().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_NDESC_OFFSET   0x00
-
- -

#include <xaxidma_hw.h>

- -

Next descriptor pointer.

- -

Referenced by XAxiDma_BdRingCheck(), XAxiDma_BdRingCreate(), and XAxiDma_DumpBd().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_NUM_WORDS   20U
-
- -

#include <xaxidma_hw.h>

- -

Total number of words for one BD.

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_START_CLEAR   8
-
- -

#include <xaxidma_hw.h>

- -

Offset to start clear.

- -

Referenced by XAxiDma_BdRingClone().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_STRIDE_VSIZE_OFFSET   0x14
-
- -

#include <xaxidma_hw.h>

- -

2D Transfer Sizes

- -

Referenced by XAxiDma_DumpBd().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_STS_ALL_ERR_MASK   0x70000000
-
- -

#include <xaxidma_hw.h>

- -

All errors.

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_STS_ALL_MASK   0xFC000000
-
- -

#include <xaxidma_hw.h>

- -

All status bits.

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_STS_COMPLETE_MASK   0x80000000
-
-
- -
-
- - - - -
#define XAXIDMA_BD_STS_DEC_ERR_MASK   0x40000000
-
- -

#include <xaxidma_hw.h>

- -

Decode error.

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_STS_INT_ERR_MASK   0x10000000
-
- -

#include <xaxidma_hw.h>

- -

Internal err.

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_STS_OFFSET   0x1C
-
-
- -
-
- - - - -
#define XAXIDMA_BD_STS_RXEOF_MASK   0x04000000
-
- -

#include <xaxidma_hw.h>

- -

Last rx pkt.

- -

Referenced by XAxiDma_BdRingFromHw().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_STS_RXSOF_MASK   0x08000000
-
- -

#include <xaxidma_hw.h>

- -

First rx pkt.

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_STS_SLV_ERR_MASK   0x20000000
-
- -

#include <xaxidma_hw.h>

- -

Slave error.

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_USR0_OFFSET   0x20
-
- -

#include <xaxidma_hw.h>

- -

User IP specific word0.

- -

Referenced by XAxiDma_BdGetAppWord(), XAxiDma_BdSetAppWord(), and XAxiDma_DumpBd().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_USR1_OFFSET   0x24
-
- -

#include <xaxidma_hw.h>

- -

User IP specific word1.

- -

Referenced by XAxiDma_DumpBd().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_USR2_OFFSET   0x28
-
- -

#include <xaxidma_hw.h>

- -

User IP specific word2.

- -

Referenced by XAxiDma_DumpBd().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_USR3_OFFSET   0x2C
-
- -

#include <xaxidma_hw.h>

- -

User IP specific word3.

- -

Referenced by XAxiDma_DumpBd().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_USR4_OFFSET   0x30
-
- -

#include <xaxidma_hw.h>

- -

User IP specific word4.

- -

Referenced by XAxiDma_DumpBd().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_WORDLEN_MASK   0xFF
-
- -

#include <xaxidma_hw.h>

- -

Whether has DRE mask.

- -

Referenced by XAxiDma_BdSetBufAddr().

- -
-
- -
-
- - - - -
#define XAXIDMA_BD_WORDLEN_SHIFT   0
-
- -

#include <xaxidma_hw.h>

- -

Whether has DRE shift.

- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdClear( BdPtr)
-
- -

#include <xaxidma_bd.h>

-Value:
memset((void *)(((UINTPTR)(BdPtr)) + XAXIDMA_BD_START_CLEAR), 0, \
- -
#define XAXIDMA_BD_BYTES_TO_CLEAR
BD specific bytes to be cleared.
Definition: xaxidma_hw.h:248
-
#define XAXIDMA_BD_START_CLEAR
Offset to start clear.
Definition: xaxidma_hw.h:247
-
-

Zero out BD specific fields.

-

BD fields that are for the BD ring or for the system hardware build information are not touched.

-
Parameters
- - -
BdPtris the BD to operate on
-
-
-
Returns
None
-
Note
C-style signature: void XAxiDma_BdClear(XAxiDma_Bd* BdPtr)
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_BdGetActualLength( BdPtr,
 LengthMask 
)
-
- -

#include <xaxidma_bd.h>

-Value:
-
LengthMask)
-
#define XAxiDma_BdRead(BaseAddress, Offset)
Read the given Buffer Descriptor word.
Definition: xaxidma_bd.h:170
-
#define XAXIDMA_BD_STS_OFFSET
Status.
Definition: xaxidma_hw.h:228
-
-

Get the actual transfer length of a BD.

-

The BD has completed in hw.

-

This function may not work if the BD is in cached memory.

-
Parameters
- - - -
BdPtris the BD to check on
LengthMaskis the Maximum Transfer Length.
-
-
-
Returns
None
-
Note
C-style signature: int XAxiDma_BdGetActualLength(XAxiDma_Bd* BdPtr)
- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdGetARCache( BdPtr)
-
- -

#include <xaxidma_bd.h>

-Value:
-
XAXIDMA_BD_ARCACHE_FIELD_MASK)
-
#define XAxiDma_BdRead(BaseAddress, Offset)
Read the given Buffer Descriptor word.
Definition: xaxidma_bd.h:170
-
#define XAXIDMA_BD_MCCTL_OFFSET
Multichannel Control Fields.
Definition: xaxidma_hw.h:225
-
-

Retrieve the ARCACHE field of the given BD previously set with XAxiDma_BdSetARCache.

-
Parameters
- - -
BdPtris the BD to operate on
-
-
-
Returns
None
-
Note
C-style signature: u32 XAxiDma_BdGetARCache(XAxiDma_Bd* BdPtr)
- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdGetARUser( BdPtr)
-
- -

#include <xaxidma_bd.h>

-Value:
-
XAXIDMA_BD_ARUSER_FIELD_MASK)
-
#define XAxiDma_BdRead(BaseAddress, Offset)
Read the given Buffer Descriptor word.
Definition: xaxidma_bd.h:170
-
#define XAXIDMA_BD_MCCTL_OFFSET
Multichannel Control Fields.
Definition: xaxidma_hw.h:225
-
-

Retrieve the ARUSER field of the given BD previously set with XAxiDma_BdSetARUser.

-
Parameters
- - -
BdPtris the BD to operate on
-
-
-
Returns
None
-
Note
C-style signature: u32 XAxiDma_BdGetARUser(XAxiDma_Bd* BdPtr)
- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdGetBufAddr( BdPtr)   (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_BUFA_OFFSET))
-
- -

#include <xaxidma_bd.h>

- -

Get the BD's buffer address.

-
Parameters
- - -
BdPtris the BD to operate on
-
-
-
Returns
None
-
Note
C-style signature: u32 XAxiDma_BdGetBufAddr(XAxiDma_Bd* BdPtr)
- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdGetCtrl( BdPtr)
-
- -

#include <xaxidma_bd.h>

-Value:
- -
#define XAXIDMA_BD_CTRL_LEN_OFFSET
Control/buffer length.
Definition: xaxidma_hw.h:227
-
#define XAXIDMA_BD_CTRL_ALL_MASK
All control bits.
Definition: xaxidma_hw.h:269
-
#define XAxiDma_BdRead(BaseAddress, Offset)
Read the given Buffer Descriptor word.
Definition: xaxidma_bd.h:170
-
-

Get the control bits for the BD.

-
Parameters
- - -
BdPtris the BD to operate on
-
-
-
Returns
The bit mask for the control of the BD
-
Note
C-style signature: u32 XAxiDma_BdGetCtrl(XAxiDma_Bd* BdPtr)
- -

Referenced by XAxiDma_BdRingToHw().

- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdGetId( BdPtr)   (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_ID_OFFSET))
-
- -

#include <xaxidma_bd.h>

- -

Retrieve the ID field of the given BD previously set with XAxiDma_BdSetId.

-
Parameters
- - -
BdPtris the BD to operate on
-
-
-
Returns
None
-
Note
C-style signature: u32 XAxiDma_BdGetId(XAxiDma_Bd* BdPtr)
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_BdGetLength( BdPtr,
 LengthMask 
)
-
- -

#include <xaxidma_bd.h>

-Value:
-
LengthMask)
-
#define XAXIDMA_BD_CTRL_LEN_OFFSET
Control/buffer length.
Definition: xaxidma_hw.h:227
-
#define XAxiDma_BdRead(BaseAddress, Offset)
Read the given Buffer Descriptor word.
Definition: xaxidma_bd.h:170
-
-

Retrieve the length field value from the given BD.

-

The returned value is the same as what was written with XAxiDma_BdSetLength(). Note that in the this value does not reflect the real length of received data. See the comments of XAxiDma_BdSetLength() for more details. To obtain the actual transfer length, use XAxiDma_BdGetActualLength().

-
Parameters
- - - -
BdPtris the BD to operate on.
LengthMaskis the Maximum Transfer Length.
-
-
-
Returns
The length value set in the BD.
-
Note
C-style signature: u32 XAxiDma_BdGetLength(XAxiDma_Bd* BdPtr)
- -

Referenced by XAxiDma_BdRingToHw().

- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdGetStride( BdPtr)
-
- -

#include <xaxidma_bd.h>

-Value:
-
XAXIDMA_BD_STRIDE_FIELD_MASK)
-
#define XAxiDma_BdRead(BaseAddress, Offset)
Read the given Buffer Descriptor word.
Definition: xaxidma_bd.h:170
-
#define XAXIDMA_BD_STRIDE_VSIZE_OFFSET
2D Transfer Sizes
Definition: xaxidma_hw.h:226
-
-

Retrieve the STRIDE field of the given BD previously set with XAxiDma_BdSetStride.

-
Parameters
- - -
BdPtris the BD to operate on
-
-
-
Returns
None
-
Note
C-style signature: u32 XAxiDma_BdGetStride(XAxiDma_Bd* BdPtr)
- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdGetSts( BdPtr)
-
- -

#include <xaxidma_bd.h>

-Value:
- -
#define XAxiDma_BdRead(BaseAddress, Offset)
Read the given Buffer Descriptor word.
Definition: xaxidma_bd.h:170
-
#define XAXIDMA_BD_STS_OFFSET
Status.
Definition: xaxidma_hw.h:228
-
#define XAXIDMA_BD_STS_ALL_MASK
All status bits.
Definition: xaxidma_hw.h:282
-
-

Retrieve the status of a BD.

-
Parameters
- - -
BdPtris the BD to operate on
-
-
-
Returns
Word at offset XAXIDMA_BD_DMASR_OFFSET. Use XAXIDMA_BD_STS_*** values defined in xaxidma_hw.h to interpret the returned value
-
Note
C-style signature: u32 XAxiDma_BdGetSts(XAxiDma_Bd* BdPtr)
- -

Referenced by XAxiDma_BdRingToHw().

- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdGetTDest( BdPtr)
-
- -

#include <xaxidma_bd.h>

-Value:
-
XAXIDMA_BD_TDEST_FIELD_MASK)
-
#define XAxiDma_BdRead(BaseAddress, Offset)
Read the given Buffer Descriptor word.
Definition: xaxidma_bd.h:170
-
#define XAXIDMA_BD_STS_OFFSET
Status.
Definition: xaxidma_hw.h:228
-
-

Retrieve the TDest field of the RX BD previously set with i XAxiDma_BdSetTDest.

-
Parameters
- - -
BdPtris the BD to operate on
-
-
-
Returns
None
-
Note
C-style signature: u32 XAxiDma_BdGetTDest(XAxiDma_Bd* BdPtr)
- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdGetTId( BdPtr)
-
- -

#include <xaxidma_bd.h>

-Value:
-
XAXIDMA_BD_TID_FIELD_MASK)
-
#define XAxiDma_BdRead(BaseAddress, Offset)
Read the given Buffer Descriptor word.
Definition: xaxidma_bd.h:170
-
#define XAXIDMA_BD_STS_OFFSET
Status.
Definition: xaxidma_hw.h:228
-
-

Retrieve the TID field of the RX BD previously set with XAxiDma_BdSetTId.

-
Parameters
- - -
BdPtris the BD to operate on
-
-
-
Returns
None
-
Note
C-style signature: u32 XAxiDma_BdGetTId(XAxiDma_Bd* BdPtr)
- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdGetTUser( BdPtr)
-
- -

#include <xaxidma_bd.h>

-Value:
-
XAXIDMA_BD_TUSER_FIELD_MASK)
-
#define XAxiDma_BdRead(BaseAddress, Offset)
Read the given Buffer Descriptor word.
Definition: xaxidma_bd.h:170
-
#define XAXIDMA_BD_STS_OFFSET
Status.
Definition: xaxidma_hw.h:228
-
-

Retrieve the TUSER field of the RX BD previously set with XAxiDma_BdSetTUser.

-
Parameters
- - -
BdPtris the BD to operate on
-
-
-
Returns
None
-
Note
C-style signature: u32 XAxiDma_BdGetTUser(XAxiDma_Bd* BdPtr)
- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdGetVSize( BdPtr)
-
- -

#include <xaxidma_bd.h>

-Value:
-
XAXIDMA_BD_VSIZE_FIELD_MASK)
-
#define XAxiDma_BdRead(BaseAddress, Offset)
Read the given Buffer Descriptor word.
Definition: xaxidma_bd.h:170
-
#define XAXIDMA_BD_STRIDE_VSIZE_OFFSET
2D Transfer Sizes
Definition: xaxidma_hw.h:226
-
-

Retrieve the STRIDE field of the given BD previously set with XAxiDma_BdSetVSize.

-
Parameters
- - -
BdPtris the BD to operate on
-
-
-
Returns
None
-
Note
C-style signature: u32 XAxiDma_BdGetVSize(XAxiDma_Bd* BdPtr)
- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdHwCompleted( BdPtr)
-
- -

#include <xaxidma_bd.h>

-Value:
- -
#define XAxiDma_BdRead(BaseAddress, Offset)
Read the given Buffer Descriptor word.
Definition: xaxidma_bd.h:170
-
#define XAXIDMA_BD_STS_OFFSET
Status.
Definition: xaxidma_hw.h:228
-
#define XAXIDMA_BD_STS_COMPLETE_MASK
Completed.
Definition: xaxidma_hw.h:275
-
-

Check whether a BD has completed in hardware.

-

This BD has been submitted to hardware. The application can use this function to poll for the completion of the BD.

-

This function may not work if the BD is in cached memory.

-
Parameters
- - -
BdPtris the BD to check on
-
-
-
Returns
    -
  • 0 if not complete
  • -
  • XAXIDMA_BD_STS_COMPLETE_MASK if completed, may contain XAXIDMA_BD_STS_*_ERR_MASK bits.
  • -
-
-
Note
C-style signature: int XAxiDma_BdHwCompleted(XAxiDma_Bd* BdPtr)
- -

Referenced by XAxiDma_UpdateBdRingCDesc().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_BdRead( BaseAddress,
 Offset 
)   (*(u32 *)((UINTPTR)((void *)(BaseAddress)) + (u32)(Offset)))
-
- -

#include <xaxidma_bd.h>

- -

Read the given Buffer Descriptor word.

-
Parameters
- - - -
BaseAddressis the base address of the BD to read
Offsetis the word offset to be read
-
-
-
Returns
The 32-bit value of the field
-
Note
C-style signature: u32 XAxiDma_BdRead(u32 BaseAddress, u32 Offset)
- -

Referenced by XAxiDma_BdGetAppWord(), XAxiDma_BdRingCheck(), XAxiDma_BdRingClone(), XAxiDma_BdRingFromHw(), XAxiDma_BdRingToHw(), XAxiDma_BdSetAppWord(), XAxiDma_BdSetBufAddr(), XAxiDma_BdSetBufAddrMicroMode(), XAxiDma_BdSetCtrl(), XAxiDma_BdSetLength(), XAxiDma_DumpBd(), and XAxiDma_StartBdRingHw().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_BdRingAckIrq( RingPtr,
 Mask 
)
-
- -

#include <xaxidma_bdring.h>

-Value:
XAxiDma_WriteReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET,\
- -
#define XAxiDma_WriteReg(BaseAddress, RegOffset, Data)
Write the given register.
Definition: xaxidma_hw.h:350
-
#define XAXIDMA_IRQ_ALL_MASK
All interrupts.
Definition: xaxidma_hw.h:194
-
#define XAXIDMA_SR_OFFSET
Status.
Definition: xaxidma_hw.h:127
-
-

Acknowledge asserted interrupts.

-

It modifies XAXIDMA_SR_OFFSET register. A mask bit set for an unasserted interrupt has no effect.

-
Parameters
- - - -
RingPtris the channel instance to operate on.
Maskare the interrupt signals to acknowledge
-
-
-
Note
C-style signature: void XAxiDma_BdRingAckIrq(XAxiDma_BdRing* RingPtr) This function is used only when system is configured as SG mode
- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdRingBusy( RingPtr)
-
- -

#include <xaxidma_bdring.h>

-Value:
-
((XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET) \
-
& XAXIDMA_IDLE_MASK) ? FALSE : TRUE))
-
#define XAXIDMA_IDLE_MASK
DMA channel idle.
Definition: xaxidma_hw.h:173
-
#define XAxiDma_ReadReg(BaseAddress, RegOffset)
Read the given register.
Definition: xaxidma_hw.h:331
-
#define XAxiDma_BdRingHwIsStarted(RingPtr)
Check whether a DMA channel is started, meaning the channel is not halted.
Definition: xaxidma_bdring.h:369
-
#define XAXIDMA_SR_OFFSET
Status.
Definition: xaxidma_hw.h:127
-
-

Check if the current DMA channel is busy with a DMA operation.

-
Parameters
- - -
RingPtris the channel instance to operate on.
-
-
-
Returns
    -
  • 1 if the DMA is busy.
  • -
  • 0 otherwise
  • -
-
-
Note
C-style signature: int XAxiDma_BdRingBusy(XAxiDma_BdRing* RingPtr) This function is used only when system is configured as SG mode
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_BdRingCntCalc( Alignment,
 Bytes 
)   (uint32_t)((Bytes)/((sizeof(XAxiDma_Bd)+((Alignment)-1))&~((Alignment)-1)))
-
- -

#include <xaxidma_bdring.h>

- -

Use this macro at initialization time to determine how many BDs will fit within the given memory constraints.

-

The results of this macro can be provided to XAxiDma_BdRingCreate().

-
Parameters
- - - -
Alignmentspecifies what byte alignment the BDs must fall on and must be a power of 2 to get an accurate calculation (32, 64, 126,...)
Bytesis the number of bytes to be used to store BDs.
-
-
-
Returns
Number of BDs that can fit in the given memory area
-
Note
C-style signature: int XAxiDma_BdRingCntCalc(u32 Alignment, u32 Bytes) This function is used only when system is configured as SG mode
- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdRingGetCnt( RingPtr)   ((RingPtr)->AllCnt)
-
- -

#include <xaxidma_bdring.h>

- -

Return the total number of BDs allocated by this channel with XAxiDma_BdRingCreate().

-
Parameters
- - -
RingPtris the BD ring to operate on.
-
-
-
Returns
The total number of BDs allocated for this channel.
-
Note
C-style signature: int XAxiDma_BdRingGetCnt(XAxiDma_BdRing* RingPtr) This function is used only when system is configured as SG mode
- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdRingGetCurrBd( RingPtr)
-
- -

#include <xaxidma_bdring.h>

-Value:
(XAxiDma_Bd *)XAxiDma_ReadReg((RingPtr)->ChanBase, \
- -
#define XAxiDma_ReadReg(BaseAddress, RegOffset)
Read the given register.
Definition: xaxidma_hw.h:331
-
UINTPTR XAxiDma_Bd[XAXIDMA_BD_NUM_WORDS]
The XAxiDma_Bd is the type for a buffer descriptor (BD).
Definition: xaxidma_bd.h:135
-
#define XAXIDMA_CDESC_OFFSET
Current descriptor pointer.
Definition: xaxidma_hw.h:128
-
-

Get the BD a BD ring is processing.

-
Parameters
- - -
RingPtris the BD ring to operate on.
-
-
-
Returns
The current BD that the BD ring is working on
-
Note
C-style signature: XAxiDma_Bd * XAxiDma_BdRingGetCurrBd(XAxiDma_BdRing* RingPtr) This function is used only when system is configured as SG mode
- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdRingGetError( RingPtr)
-
- -

#include <xaxidma_bdring.h>

-Value:
(XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET) \
- -
#define XAxiDma_ReadReg(BaseAddress, RegOffset)
Read the given register.
Definition: xaxidma_hw.h:331
-
#define XAXIDMA_ERR_ALL_MASK
All errors.
Definition: xaxidma_hw.h:184
-
#define XAXIDMA_SR_OFFSET
Status.
Definition: xaxidma_hw.h:127
-
-

Get error bits of a DMA channel.

-
Parameters
- - -
RingPtris the channel instance to operate on.
-
-
-
Returns
Rrror bits in the status register, they should be interpreted with XAXIDMA_ERR_*_MASK defined in xaxidma_hw.h
-
Note
C-style signature: u32 XAxiDma_BdRingGetError(XAxiDma_BdRing* RingPtr) This function is used only when system is configured as SG mode
- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdRingGetFreeCnt( RingPtr)   ((RingPtr)->FreeCnt)
-
- -

#include <xaxidma_bdring.h>

- -

Return the number of BDs allocatable with XAxiDma_BdRingAlloc() for pre- processing.

-
Parameters
- - -
RingPtris the BD ring to operate on.
-
-
-
Returns
The number of BDs currently allocatable.
-
Note
C-style signature: int XAxiDma_BdRingGetFreeCnt(XAxiDma_BdRing* RingPtr) This function is used only when system is configured as SG mode
- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdRingGetIrq( RingPtr)
-
- -

#include <xaxidma_bdring.h>

-Value:
(XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET) \
- -
#define XAxiDma_ReadReg(BaseAddress, RegOffset)
Read the given register.
Definition: xaxidma_hw.h:331
-
#define XAXIDMA_IRQ_ALL_MASK
All interrupts.
Definition: xaxidma_hw.h:194
-
#define XAXIDMA_SR_OFFSET
Status.
Definition: xaxidma_hw.h:127
-
-

Retrieve the contents of the channel's IRQ register XAXIDMA_SR_OFFSET.

-

This operation can be used to see which interrupts are pending.

-
Parameters
- - -
RingPtris the channel instance to operate on.
-
-
-
Returns
Current contents of the IRQ_OFFSET register. Use XAXIDMA_IRQ_*** values defined in xaxidma_hw.h to interpret the returned value.
-
Note
C-style signature: u32 XAxiDma_BdRingGetIrq(XAxiDma_BdRing* RingPtr) This function is used only when system is configured as SG mode
- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdRingGetSr( RingPtr)   XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET)
-
- -

#include <xaxidma_bdring.h>

- -

Retrieve the contents of the channel status register.

-
Parameters
- - -
RingPtris the channel instance to operate on.
-
-
-
Returns
Current contents of status register
-
Note
C-style signature: u32 XAxiDma_BdRingGetSr(XAxiDma_BdRing* RingPtr) This function is used only when system is configured as SG mode
- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdRingHwIsStarted( RingPtr)
-
- -

#include <xaxidma_bdring.h>

-Value:
((XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET) \
-
& XAXIDMA_HALTED_MASK) ? FALSE : TRUE)
-
#define XAxiDma_ReadReg(BaseAddress, RegOffset)
Read the given register.
Definition: xaxidma_hw.h:331
-
#define XAXIDMA_HALTED_MASK
DMA channel halted.
Definition: xaxidma_hw.h:172
-
#define XAXIDMA_SR_OFFSET
Status.
Definition: xaxidma_hw.h:127
-
-

Check whether a DMA channel is started, meaning the channel is not halted.

-
Parameters
- - -
RingPtris the channel instance to operate on.
-
-
-
Returns
    -
  • 1 if channel is started
  • -
  • 0 otherwise
  • -
-
-
Note
C-style signature: int XAxiDma_BdRingHwIsStarted(XAxiDma_BdRing* RingPtr)
- -

Referenced by XAxiDma_StartBdRingHw(), and XAxiDma_UpdateBdRingCDesc().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_BdRingIntDisable( RingPtr,
 Mask 
)
-
- -

#include <xaxidma_bdring.h>

-Value:
(XAxiDma_WriteReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET, \
-
XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET) & \
-
~((Mask) & XAXIDMA_IRQ_ALL_MASK)))
-
#define XAxiDma_ReadReg(BaseAddress, RegOffset)
Read the given register.
Definition: xaxidma_hw.h:331
-
#define XAxiDma_WriteReg(BaseAddress, RegOffset, Data)
Write the given register.
Definition: xaxidma_hw.h:350
-
#define XAXIDMA_IRQ_ALL_MASK
All interrupts.
Definition: xaxidma_hw.h:194
-
#define XAXIDMA_CR_OFFSET
Channel control.
Definition: xaxidma_hw.h:126
-
-

Clear interrupt enable bits for a channel.

-

It modifies the XAXIDMA_CR_OFFSET register.

-
Parameters
- - - -
RingPtris the channel instance to operate on.
Maskconsists of the interrupt signals to disable.Bits not specified in the Mask are not affected.
-
-
-
Note
C-style signature: void XAxiDma_BdRingIntDisable(XAxiDma_BdRing* RingPtr, u32 Mask) This function is used only when system is configured as SG mode
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_BdRingIntEnable( RingPtr,
 Mask 
)
-
- -

#include <xaxidma_bdring.h>

-Value:
(XAxiDma_WriteReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET, \
-
XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET) \
-
| ((Mask) & XAXIDMA_IRQ_ALL_MASK)))
-
#define XAxiDma_ReadReg(BaseAddress, RegOffset)
Read the given register.
Definition: xaxidma_hw.h:331
-
#define XAxiDma_WriteReg(BaseAddress, RegOffset, Data)
Write the given register.
Definition: xaxidma_hw.h:350
-
#define XAXIDMA_IRQ_ALL_MASK
All interrupts.
Definition: xaxidma_hw.h:194
-
#define XAXIDMA_CR_OFFSET
Channel control.
Definition: xaxidma_hw.h:126
-
-

Set interrupt enable bits for a channel.

-

This operation will modify the XAXIDMA_CR_OFFSET register.

-
Parameters
- - - -
RingPtris the channel instance to operate on.
Maskconsists of the interrupt signals to enable.Bits not specified in the mask are not affected.
-
-
-
Note
C-style signature: void XAxiDma_BdRingIntEnable(XAxiDma_BdRing* RingPtr, u32 Mask) This function is used only when system is configured as SG mode
- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdRingIntGetEnabled( RingPtr)
-
- -

#include <xaxidma_bdring.h>

-Value:
(XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET) \
- -
#define XAxiDma_ReadReg(BaseAddress, RegOffset)
Read the given register.
Definition: xaxidma_hw.h:331
-
#define XAXIDMA_IRQ_ALL_MASK
All interrupts.
Definition: xaxidma_hw.h:194
-
#define XAXIDMA_CR_OFFSET
Channel control.
Definition: xaxidma_hw.h:126
-
-

Get enabled interrupts of a channel.

-

It is in XAXIDMA_CR_OFFSET register.

-
Parameters
- - -
RingPtris the channel instance to operate on.
-
-
-
Returns
Enabled interrupts of a channel. Use XAXIDMA_IRQ_* defined in xaxidma_hw.h to interpret this returned value.
-
Note
C-style signature: u32 XAxiDma_BdRingIntGetEnabled(XAxiDma_BdRing* RingPtr) This function is used only when system is configured as SG mode
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_BdRingMemCalc( Alignment,
 NumBd 
)   (int)((sizeof(XAxiDma_Bd)+((Alignment)-1)) & ~((Alignment)-1))*(NumBd)
-
- -

#include <xaxidma_bdring.h>

- -

Use this macro at initialization time to determine how many bytes of memory are required to contain a given number of BDs at a given alignment.

-
Parameters
- - - -
Alignmentspecifies what byte alignment the BDs must fall on. This parameter must be a power of 2 to get an accurate calculation (32, 64,128,...)
NumBdis the number of BDs to calculate memory size requirements
-
-
-
Returns
The number of bytes of memory required to create a BD list with the given memory constraints.
-
Note
C-style signature: int XAxiDma_BdRingMemCalc(u32 Alignment, u32 NumBd) This function is used only when system is configured as SG mode
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_BdRingNext( RingPtr,
 BdPtr 
)
-
- -

#include <xaxidma_bdring.h>

-Value:
(((UINTPTR)(BdPtr) >= (RingPtr)->LastBdAddr) ? \
-
(UINTPTR)(RingPtr)->FirstBdAddr : \
-
(UINTPTR)((UINTPTR)(BdPtr) + (RingPtr)->Separation))
-
-

Return the next BD in the ring.

-
Parameters
- - - -
RingPtris the BD ring to operate on.
BdPtris the current BD.
-
-
-
Returns
The next BD in the ring relative to the BdPtr parameter.
-
Note
C-style signature: XAxiDma_Bd *XAxiDma_BdRingNext(XAxiDma_BdRing* RingPtr, XAxiDma_Bd *BdPtr) This function is used only when system is configured as SG mode
- -

Referenced by XAxiDma_BdRingFromHw(), XAxiDma_BdRingToHw(), and XAxiDma_UpdateBdRingCDesc().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_BdRingPrev( RingPtr,
 BdPtr 
)
-
- -

#include <xaxidma_bdring.h>

-Value:
(((u32)(BdPtr) <= (RingPtr)->FirstBdAddr) ? \
-
(XAxiDma_Bd*)(RingPtr)->LastBdAddr : \
-
(XAxiDma_Bd*)((u32)(BdPtr) - (RingPtr)->Separation))
-
UINTPTR XAxiDma_Bd[XAXIDMA_BD_NUM_WORDS]
The XAxiDma_Bd is the type for a buffer descriptor (BD).
Definition: xaxidma_bd.h:135
-
-

Return the previous BD in the ring.

-
Parameters
- - - -
RingPtris the DMA channel to operate on.
BdPtris the current BD.
-
-
-
Returns
The previous BD in the ring relative to the BdPtr parameter.
-
Note
C-style signature: XAxiDma_Bd *XAxiDma_BdRingPrev(XAxiDma_BdRing* RingPtr, XAxiDma_Bd *BdPtr) This function is used only when system is configured as SG mode
- -
-
- -
-
- - - - - - - - -
#define XAxiDma_BdRingSnapShotCurrBd( RingPtr)
-
- -

#include <xaxidma_bdring.h>

-Value:
{ \
-
if (!RingPtr->IsRxChannel) { \
-
(RingPtr)->BdaRestart = \
-
XAxiDma_ReadReg((RingPtr)->ChanBase, \
- -
} else { \
-
if (!RingPtr->RingIndex) { \
-
(RingPtr)->BdaRestart = \
- -
(RingPtr)->ChanBase, \
- -
} else { \
-
(RingPtr)->BdaRestart = \
- -
(RingPtr)->ChanBase, \
- -
(RingPtr->RingIndex - 1) * \
- -
} \
-
} \
-
}
-
#define XAxiDma_ReadReg(BaseAddress, RegOffset)
Read the given register.
Definition: xaxidma_hw.h:331
-
#define XAXIDMA_RX_NDESC_OFFSET
Rx Next Descriptor Offset.
Definition: xaxidma_hw.h:148
-
#define XAXIDMA_RX_CDESC0_OFFSET
Multi-Channel DMA Descriptor Offsets.
Definition: xaxidma_hw.h:144
-
#define XAXIDMA_CDESC_OFFSET
Current descriptor pointer.
Definition: xaxidma_hw.h:128
-
-

Snap shot the latest BD a BD ring is processing.

-
Parameters
- - -
RingPtris the BD ring to operate on.
-
-
-
Returns
None
-
Note
C-style signature: void XAxiDma_BdRingSnapShotCurrBd(XAxiDma_BdRing* RingPtr) This function is used only when system is configured as SG mode
- -

Referenced by XAxiDma_Reset().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_BdSetARCache( BdPtr,
 ARCache 
)
-
- -

#include <xaxidma_bd.h>

-Value:
{ \
-
u32 val; \
- -
~XAXIDMA_BD_ARCACHE_FIELD_MASK); \
-
val |= ((u32)(ARCache) << XAXIDMA_BD_ARCACHE_FIELD_SHIFT); \
- -
}
-
#define XAxiDma_BdWrite(BaseAddress, Offset, Data)
Write the given Buffer Descriptor word.
Definition: xaxidma_bd.h:189
-
#define XAxiDma_BdRead(BaseAddress, Offset)
Read the given Buffer Descriptor word.
Definition: xaxidma_bd.h:170
-
#define XAXIDMA_BD_MCCTL_OFFSET
Multichannel Control Fields.
Definition: xaxidma_hw.h:225
-
-

Set the ARCACHE field of the given BD.

-

This signal provides additional information about the cacheable characteristics of the transfer.

-
Parameters
- - - -
BdPtris the BD to operate on
ARCacheis a 8 bit quantity to set in the BD
-
-
-
Returns
None
-
Note
C-style signature: void XAxiDma_BdSetARCache(XAxiDma_Bd* BdPtr, void ARCache)
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_BdSetARUser( BdPtr,
 ARUser 
)
-
- -

#include <xaxidma_bd.h>

-Value:
{ \
-
u32 val; \
- -
~XAXIDMA_BD_ARUSER_FIELD_MASK); \
-
val |= ((u32)(ARUser) << XAXIDMA_BD_ARUSER_FIELD_SHIFT); \
- -
}
-
#define XAxiDma_BdWrite(BaseAddress, Offset, Data)
Write the given Buffer Descriptor word.
Definition: xaxidma_bd.h:189
-
#define XAxiDma_BdRead(BaseAddress, Offset)
Read the given Buffer Descriptor word.
Definition: xaxidma_bd.h:170
-
#define XAXIDMA_BD_MCCTL_OFFSET
Multichannel Control Fields.
Definition: xaxidma_hw.h:225
-
-

Set the ARUSER field of the given BD.

-

Sideband signals used for user defined information.

-
Parameters
- - - -
BdPtris the BD to operate on
ARUseris a 8 bit quantity to set in the BD
-
-
-
Returns
None
-
Note
C-style signature: void XAxiDma_BdSetARUser(XAxiDma_Bd* BdPtr, void ARUser)
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_BdSetId( BdPtr,
 Id 
)   (XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_ID_OFFSET, (u32)(Id)))
-
- -

#include <xaxidma_bd.h>

- -

Set the ID field of the given BD.

-

The ID is an arbitrary piece of data the application can associate with a specific BD.

-
Parameters
- - - -
BdPtris the BD to operate on
Idis a 32 bit quantity to set in the BD
-
-
-
Returns
None
-
Note
C-style signature: void XAxiDma_BdSetId(XAxiDma_Bd* BdPtr, void Id)
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_BdSetStride( BdPtr,
 Stride 
)
-
- -

#include <xaxidma_bd.h>

-Value:
{ \
-
u32 val; \
- -
~XAXIDMA_BD_STRIDE_FIELD_MASK); \
-
val |= ((u32)(Stride) << XAXIDMA_BD_STRIDE_FIELD_SHIFT); \
- -
}
-
#define XAxiDma_BdWrite(BaseAddress, Offset, Data)
Write the given Buffer Descriptor word.
Definition: xaxidma_bd.h:189
-
#define XAxiDma_BdRead(BaseAddress, Offset)
Read the given Buffer Descriptor word.
Definition: xaxidma_bd.h:170
-
#define XAXIDMA_BD_STRIDE_VSIZE_OFFSET
2D Transfer Sizes
Definition: xaxidma_hw.h:226
-
-

Set the STRIDE field of the given BD.

-

It is the address distance between the first address of successive horizontal reads.

-
Parameters
- - - -
BdPtris the BD to operate on
Strideis a 32 bit quantity to set in the BD
-
-
-
Returns
None
-
Note
C-style signature: void XAxiDma_BdSetStride(XAxiDma_Bd* BdPtr, void Stride)
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_BdSetTDest( BdPtr,
 TDest 
)
-
- -

#include <xaxidma_bd.h>

-Value:
{ \
-
u32 val; \
- -
~XAXIDMA_BD_TDEST_FIELD_MASK); \
-
val |= ((u32)(TDest) << XAXIDMA_BD_TDEST_FIELD_SHIFT); \
- -
}
-
#define XAxiDma_BdWrite(BaseAddress, Offset, Data)
Write the given Buffer Descriptor word.
Definition: xaxidma_bd.h:189
-
#define XAxiDma_BdRead(BaseAddress, Offset)
Read the given Buffer Descriptor word.
Definition: xaxidma_bd.h:170
-
#define XAXIDMA_BD_MCCTL_OFFSET
Multichannel Control Fields.
Definition: xaxidma_hw.h:225
-
-

Set the TDEST field of the TX BD.

-

Provides coarse routing information for the data stream.

-
Parameters
- - - -
BdPtris the BD to operate on
TDestis a 8 bit quantity to set in the BD
-
-
-
Returns
None
-
Note
C-style signature: void XAxiDma_BdSetTDest(XAxiDma_Bd* BdPtr, void TDest)
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_BdSetTId( BdPtr,
 TId 
)
-
- -

#include <xaxidma_bd.h>

-Value:
{ \
-
u32 val; \
- -
~XAXIDMA_BD_TID_FIELD_MASK); \
-
val |= ((u32)(TId) << XAXIDMA_BD_TID_FIELD_SHIFT); \
- -
}
-
#define XAxiDma_BdWrite(BaseAddress, Offset, Data)
Write the given Buffer Descriptor word.
Definition: xaxidma_bd.h:189
-
#define XAxiDma_BdRead(BaseAddress, Offset)
Read the given Buffer Descriptor word.
Definition: xaxidma_bd.h:170
-
#define XAXIDMA_BD_MCCTL_OFFSET
Multichannel Control Fields.
Definition: xaxidma_hw.h:225
-
-

Set the TID field of the TX BD.

-

Provides a stream identifier and can be used to differentiate between multiple streams of data that are being transferred across the same interface.

-
Parameters
- - - -
BdPtris the BD to operate on
TIdis a 8 bit quantity to set in the BD
-
-
-
Returns
None
-
Note
C-style signature: void XAxiDma_BdSetTId(XAxiDma_Bd* BdPtr, void TId)
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_BdSetTUser( BdPtr,
 TUser 
)
-
- -

#include <xaxidma_bd.h>

-Value:
{ \
-
u32 val; \
- -
~XAXIDMA_BD_TUSER_FIELD_MASK); \
-
val |= ((u32)(TUser) << XAXIDMA_BD_TUSER_FIELD_SHIFT); \
- -
}
-
#define XAxiDma_BdWrite(BaseAddress, Offset, Data)
Write the given Buffer Descriptor word.
Definition: xaxidma_bd.h:189
-
#define XAxiDma_BdRead(BaseAddress, Offset)
Read the given Buffer Descriptor word.
Definition: xaxidma_bd.h:170
-
#define XAXIDMA_BD_MCCTL_OFFSET
Multichannel Control Fields.
Definition: xaxidma_hw.h:225
-
-

Set the TUSER field of the TX BD.

-

User defined sideband signaling.

-
Parameters
- - - -
BdPtris the BD to operate on
TUseris a 8 bit quantity to set in the BD
-
-
-
Returns
None
-
Note
C-style signature: void XAxiDma_BdSetTUser(XAxiDma_Bd* BdPtr, void TUser)
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_BdSetVSize( BdPtr,
 VSize 
)
-
- -

#include <xaxidma_bd.h>

-Value:
{ \
-
u32 val; \
- -
~XAXIDMA_BD_VSIZE_FIELD_MASK); \
-
val |= ((u32)(VSize) << XAXIDMA_BD_VSIZE_FIELD_SHIFT); \
- -
}
-
#define XAxiDma_BdWrite(BaseAddress, Offset, Data)
Write the given Buffer Descriptor word.
Definition: xaxidma_bd.h:189
-
#define XAxiDma_BdRead(BaseAddress, Offset)
Read the given Buffer Descriptor word.
Definition: xaxidma_bd.h:170
-
#define XAXIDMA_BD_STRIDE_VSIZE_OFFSET
2D Transfer Sizes
Definition: xaxidma_hw.h:226
-
-

Set the VSIZE field of the given BD.

-

Number of horizontal lines for strided access.

-
Parameters
- - - -
BdPtris the BD to operate on
VSizeis a 32 bit quantity to set in the BD
-
-
-
Returns
None
-
Note
C-style signature: void XAxiDma_BdSetVSize(XAxiDma_Bd* BdPtr, void VSize)
- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
#define XAxiDma_BdWrite( BaseAddress,
 Offset,
 Data 
)   (*(u32 *)((UINTPTR)(void *)(BaseAddress) + (u32)(Offset))) = (u32)(Data)
-
- -

#include <xaxidma_bd.h>

- -

Write the given Buffer Descriptor word.

-
Parameters
- - - - -
BaseAddressis the base address of the BD to write
Offsetis the word offset to be written
Datais the 32-bit value to write to the field
-
-
-
Returns
None.
-
Note
C-style signature: void XAxiDma_BdWrite(u32 BaseAddress, u32 RegOffset, u32 Data)
- -

Referenced by XAxiDma_BdRingClone(), XAxiDma_BdRingCreate(), XAxiDma_BdRingToHw(), XAxiDma_BdSetAppWord(), XAxiDma_BdSetBufAddr(), XAxiDma_BdSetBufAddrMicroMode(), XAxiDma_BdSetCtrl(), and XAxiDma_BdSetLength().

- -
-
- -
-
- - - - -
#define XAXIDMA_BUFFLEN_OFFSET   0x00000028
-
- -

#include <xaxidma_hw.h>

- -

Tail descriptor pointer.

- -

Referenced by XAxiDma_SimpleTransfer().

- -
-
- -
-
- - - - -
#define XAXIDMA_CDESC_MSB_OFFSET   0x0000000C
-
- -

#include <xaxidma_hw.h>

- -

Current descriptor pointer.

- -

Referenced by XAxiDma_UpdateBdRingCDesc().

- -
-
- -
-
- - - - -
#define XAXIDMA_CDESC_OFFSET   0x00000008
-
- -

#include <xaxidma_hw.h>

- -

Current descriptor pointer.

- -

Referenced by XAxiDma_BdRingDumpRegs(), and XAxiDma_UpdateBdRingCDesc().

- -
-
- -
-
- - - - -
#define XAXIDMA_COALESCE_MASK   0x00FF0000
-
- -

#include <xaxidma_hw.h>

- -

Coalesce counter.

- -

Referenced by XAxiDma_BdRingGetCoalesce(), and XAxiDma_BdRingSetCoalesce().

- -
-
- -
-
- - - - -
#define XAXIDMA_CR_CYCLIC_MASK   0x00000010
-
- -

#include <xaxidma_hw.h>

- -

Cyclic Mode.

- -

Referenced by XAxiDma_SelectCyclicMode().

- -
-
- -
-
- - - - -
#define XAXIDMA_CR_KEYHOLE_MASK   0x00000008
-
- -

#include <xaxidma_hw.h>

- -

Keyhole feature.

- -

Referenced by XAxiDma_SelectKeyHole().

- -
-
- - - -
-
- - - - -
#define XAXIDMA_CR_RESET_MASK   0x00000004
-
- -

#include <xaxidma_hw.h>

- -

Reset DMA engine.

- -

Referenced by XAxiDma_Reset(), and XAxiDma_ResetIsDone().

- -
-
- -
-
- - - - -
#define XAXIDMA_CR_RUNSTOP_MASK   0x00000001
-
- -

#include <xaxidma_hw.h>

- -

Start/stop DMA channel.

- -

Referenced by XAxiDma_Pause(), XAxiDma_SimpleTransfer(), and XAxiDma_StartBdRingHw().

- -
-
- -
-
- - - - -
#define XAXIDMA_DELAY_MASK   0xFF000000
-
- -

#include <xaxidma_hw.h>

- -

Delay timeout counter.

- -

Referenced by XAxiDma_BdRingGetCoalesce(), and XAxiDma_BdRingSetCoalesce().

- -
-
- -
-
- - - - -
#define XAXIDMA_DESC_LSB_MASK   (0xFFFFFFC0U)
-
-
- -
-
- - - - -
#define XAXIDMA_DESTADDR_MSB_OFFSET   0x0000001C
-
- -

#include <xaxidma_hw.h>

- -

Simple mode destination address pointer.

- -

Referenced by XAxiDma_SimpleTransfer().

- -
-
- -
-
- - - - -
#define XAXIDMA_DESTADDR_OFFSET   0x00000018
-
- -

#include <xaxidma_hw.h>

- -

Simple mode destination address pointer.

- -

Referenced by XAxiDma_SimpleTransfer().

- -
-
- -
-
- - - - -
#define XAXIDMA_ERR_ALL_MASK   0x00000770
-
- -

#include <xaxidma_hw.h>

- -

All errors.

- -
-
- -
-
- - - - -
#define XAXIDMA_ERR_DECODE_MASK   0x00000040
-
- -

#include <xaxidma_hw.h>

- -

Datamover decode err.

- -
-
- -
-
- - - - -
#define XAXIDMA_ERR_INTERNAL_MASK   0x00000010
-
- -

#include <xaxidma_hw.h>

- -

Datamover internal err.

- -
-
- -
-
- - - - -
#define XAXIDMA_ERR_SG_DEC_MASK   0x00000400
-
- -

#include <xaxidma_hw.h>

- -

SG decode err.

- -
-
- -
-
- - - - -
#define XAXIDMA_ERR_SG_INT_MASK   0x00000100
-
- -

#include <xaxidma_hw.h>

- -

SG internal err.

- -
-
- -
-
- - - - -
#define XAXIDMA_ERR_SG_SLV_MASK   0x00000200
-
- -

#include <xaxidma_hw.h>

- -

SG slave err.

- -
-
- -
-
- - - - -
#define XAXIDMA_ERR_SLAVE_MASK   0x00000020
-
- -

#include <xaxidma_hw.h>

- -

Datamover slave err.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_GetRxIndexRing( InstancePtr,
 RingIndex 
)   (&((InstancePtr)->RxBdRing[RingIndex]))
-
- -

#include <xaxidma.h>

- -

Get Receive (Rx) Ring ptr of a Index.

-

Warning: This has a different API than the LLDMA driver. It now returns the pointer to the BD ring.

-
Parameters
- - - -
InstancePtris a pointer to the DMA engine instance to be worked on.
RingIndexis the channel Index.
-
-
-
Returns
Pointer to the Rx Ring
-
Note
C-style signature: XAxiDma_BdRing * XAxiDma_GetRxIndexRing(XAxiDma * InstancePtr, int RingIndex) This function is used only when system is configured as SG mode
- -

Referenced by XAxiDma_Pause(), XAxiDma_Reset(), and XAxiDma_Resume().

- -
-
- -
-
- - - - - - - - -
#define XAxiDma_GetRxRing( InstancePtr)   (&((InstancePtr)->RxBdRing[0]))
-
- -

#include <xaxidma.h>

- -

Get Receive (Rx) Ring ptr.

-

Warning: This has a different API than the LLDMA driver. It now returns the pointer to the BD ring.

-
Parameters
- - -
InstancePtris a pointer to the DMA engine instance to be worked on.
-
-
-
Returns
Pointer to the Rx Ring
-
Note
C-style signature: XAxiDma_BdRing * XAxiDma_GetRxRing(XAxiDma * InstancePtr) This function is used only when system is configured as SG mode
- -

Referenced by XAxiDma_ResetIsDone().

- -
-
- -
-
- - - - - - - - -
#define XAxiDma_GetTxRing( InstancePtr)   (&((InstancePtr)->TxBdRing))
-
- -

#include <xaxidma.h>

- -

Get Transmit (Tx) Ring ptr.

-

Warning: This has a different API than the LLDMA driver. It now returns the pointer to the BD ring.

-
Parameters
- - -
InstancePtris a pointer to the DMA engine instance to be worked on.
-
-
-
Returns
Pointer to the Tx Ring
-
Note
C-style signature: XAxiDma_BdRing * XAxiDma_GetTxRing(XAxiDma * InstancePtr) This function is used only when system is configured as SG mode
- -

Referenced by XAxiDma_Pause(), XAxiDma_Reset(), XAxiDma_ResetIsDone(), and XAxiDma_Resume().

- -
-
- -
-
- - - - -
#define XAXIDMA_HALTED_MASK   0x00000001
-
- -

#include <xaxidma_hw.h>

- -

DMA channel halted.

- -

Referenced by XAxiDma_SimpleTransfer().

- -
-
- -
-
- - - - - - - - -
#define XAxiDma_HasSg( InstancePtr)   ((InstancePtr)->HasSg) ? TRUE : FALSE
-
- -

#include <xaxidma.h>

- -

This function checks whether system is configured as Simple or Scatter Gather mode.

-
Parameters
- - -
InstancePtris a pointer to the DMA engine instance to be worked on.
-
-
-
Returns
    -
  • TRUE if configured as SG mode
  • -
  • FALSE if configured as simple mode
  • -
-
-
Note
None
- -

Referenced by XAxiDma_Pause(), XAxiDma_Reset(), XAxiDma_Resume(), and XAxiDma_SimpleTransfer().

- -
-
- -
-
- - - - -
#define XAXIDMA_IDLE_MASK   0x00000002
-
- -

#include <xaxidma_hw.h>

- -

DMA channel idle.

- -

Referenced by XAxiDma_Busy().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
#define XAxiDma_IntrAckIrq( InstancePtr,
 Mask,
 Direction 
)
-
- -

#include <xaxidma.h>

-Value:
XAxiDma_WriteReg((InstancePtr)->RegBase + \
- - -
#define XAXIDMA_RX_OFFSET
RX channel registers base offset.
Definition: xaxidma_hw.h:118
-
#define XAxiDma_WriteReg(BaseAddress, RegOffset, Data)
Write the given register.
Definition: xaxidma_hw.h:350
-
#define XAXIDMA_IRQ_ALL_MASK
All interrupts.
Definition: xaxidma_hw.h:194
-
#define XAXIDMA_SR_OFFSET
Status.
Definition: xaxidma_hw.h:127
-
-

This function acknowledges the interrupts that are specified in Mask.

-
Parameters
- - - - -
InstancePtris the driver instance we are working on
Maskis the mask for the interrupts to be acknowledge
Directionis DMA transfer direction, valid values are
    -
  • XAXIDMA_DMA_TO_DEVICE.
  • -
  • XAXIDMA_DEVICE_TO_DMA.
  • -
-
-
-
-
Returns
None
-
Note
None.
- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
#define XAxiDma_IntrDisable( InstancePtr,
 Mask,
 Direction 
)
-
- -

#include <xaxidma.h>

-Value:
XAxiDma_WriteReg((InstancePtr)->RegBase + \
- -
(XAxiDma_ReadReg((InstancePtr)->RegBase + \
- -
& ~(Mask & XAXIDMA_IRQ_ALL_MASK))
-
#define XAXIDMA_RX_OFFSET
RX channel registers base offset.
Definition: xaxidma_hw.h:118
-
#define XAxiDma_ReadReg(BaseAddress, RegOffset)
Read the given register.
Definition: xaxidma_hw.h:331
-
#define XAxiDma_WriteReg(BaseAddress, RegOffset, Data)
Write the given register.
Definition: xaxidma_hw.h:350
-
#define XAXIDMA_IRQ_ALL_MASK
All interrupts.
Definition: xaxidma_hw.h:194
-
#define XAXIDMA_CR_OFFSET
Channel control.
Definition: xaxidma_hw.h:126
-
-

This function disables interrupts specified by the Mask.

-

Interrupts that are not in the mask are not affected.

-
Parameters
- - - - -
InstancePtris the driver instance we are working on
Maskis the mask for the interrupts to be disabled
Directionis DMA transfer direction, valid values are
    -
  • XAXIDMA_DMA_TO_DEVICE.
  • -
  • XAXIDMA_DEVICE_TO_DMA.
  • -
-
-
-
-
Returns
None
-
Note
None
- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
#define XAxiDma_IntrEnable( InstancePtr,
 Mask,
 Direction 
)
-
- -

#include <xaxidma.h>

-Value:
XAxiDma_WriteReg((InstancePtr)->RegBase + \
- -
(XAxiDma_ReadReg((InstancePtr)->RegBase + \
- - -
#define XAXIDMA_RX_OFFSET
RX channel registers base offset.
Definition: xaxidma_hw.h:118
-
#define XAxiDma_ReadReg(BaseAddress, RegOffset)
Read the given register.
Definition: xaxidma_hw.h:331
-
#define XAxiDma_WriteReg(BaseAddress, RegOffset, Data)
Write the given register.
Definition: xaxidma_hw.h:350
-
#define XAXIDMA_IRQ_ALL_MASK
All interrupts.
Definition: xaxidma_hw.h:194
-
#define XAXIDMA_CR_OFFSET
Channel control.
Definition: xaxidma_hw.h:126
-
-

This function enables interrupts specified by the Mask in specified direction, Interrupts that are not in the mask are not affected.

-
Parameters
- - - - -
InstancePtris the driver instance we are working on
Maskis the mask for the interrupts to be enabled
Directionis DMA transfer direction, valid values are
    -
  • XAXIDMA_DMA_TO_DEVICE.
  • -
  • XAXIDMA_DEVICE_TO_DMA.
  • -
-
-
-
-
Returns
None
-
Note
None
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_IntrGetEnabled( InstancePtr,
 Direction 
)
-
- -

#include <xaxidma.h>

-Value:
XAxiDma_ReadReg((InstancePtr)->RegBase + \
- - -
#define XAXIDMA_RX_OFFSET
RX channel registers base offset.
Definition: xaxidma_hw.h:118
-
#define XAxiDma_ReadReg(BaseAddress, RegOffset)
Read the given register.
Definition: xaxidma_hw.h:331
-
#define XAXIDMA_IRQ_ALL_MASK
All interrupts.
Definition: xaxidma_hw.h:194
-
#define XAXIDMA_CR_OFFSET
Channel control.
Definition: xaxidma_hw.h:126
-
-

This function gets the mask for the interrupts that are currently enabled.

-
Parameters
- - - -
InstancePtris the driver instance we are working on
Directionis DMA transfer direction, valid values are
    -
  • XAXIDMA_DMA_TO_DEVICE.
  • -
  • XAXIDMA_DEVICE_TO_DMA.
  • -
-
-
-
-
Returns
The bit mask for the interrupts that are currently enabled
-
Note
None
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_IntrGetIrq( InstancePtr,
 Direction 
)
-
- -

#include <xaxidma.h>

-Value:
(XAxiDma_ReadReg((InstancePtr)->RegBase + \
- - -
#define XAXIDMA_RX_OFFSET
RX channel registers base offset.
Definition: xaxidma_hw.h:118
-
#define XAxiDma_ReadReg(BaseAddress, RegOffset)
Read the given register.
Definition: xaxidma_hw.h:331
-
#define XAXIDMA_IRQ_ALL_MASK
All interrupts.
Definition: xaxidma_hw.h:194
-
#define XAXIDMA_SR_OFFSET
Status.
Definition: xaxidma_hw.h:127
-
-

This function gets the interrupts that are asserted.

-
Parameters
- - - -
InstancePtris the driver instance we are working on
Directionis DMA transfer direction, valid values are
    -
  • XAXIDMA_DMA_TO_DEVICE.
  • -
  • XAXIDMA_DEVICE_TO_DMA.
  • -
-
-
-
-
Returns
The bit mask for the interrupts asserted.
-
Note
None
- -
-
- -
-
- - - - -
#define XAXIDMA_IRQ_ALL_MASK   0x00007000
-
- -

#include <xaxidma_hw.h>

- -

All interrupts.

- -
-
- -
-
- - - - -
#define XAXIDMA_IRQ_DELAY_MASK   0x00002000
-
- -

#include <xaxidma_hw.h>

- -

Delay interrupt.

- -
-
- -
-
- - - - -
#define XAXIDMA_IRQ_ERROR_MASK   0x00004000
-
- -

#include <xaxidma_hw.h>

- -

Error interrupt.

- -
-
- -
-
- - - - -
#define XAXIDMA_IRQ_IOC_MASK   0x00001000
-
- -

#include <xaxidma_hw.h>

- -

Completion intr.

- -
-
- -
-
- - - - -
#define XAXIDMA_MICROMODE_MIN_BUF_ALIGN   0xFFF
-
- -

#include <xaxidma_hw.h>

- -

Minimum byte alignment requirement for buffer address in Micro DMA mode.

- -

Referenced by XAxiDma_BdSetBufAddrMicroMode(), and XAxiDma_SimpleTransfer().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
#define XAxiDma_ReadReg( BaseAddress,
 RegOffset 
)   XAxiDma_In32((BaseAddress) + (RegOffset))
-
- -

#include <xaxidma_hw.h>

- -

Read the given register.

-
Parameters
- - - -
BaseAddressis the base address of the device
RegOffsetis the register offset to be read
-
-
-
Returns
The 32-bit value of the register
-
Note
C-style signature: u32 XAxiDma_ReadReg(u32 BaseAddress, u32 RegOffset)
- -

Referenced by XAxiDma_BdRingDumpRegs(), XAxiDma_BdRingGetCoalesce(), XAxiDma_BdRingSetCoalesce(), XAxiDma_Busy(), XAxiDma_Pause(), XAxiDma_ResetIsDone(), XAxiDma_SelectCyclicMode(), XAxiDma_SelectKeyHole(), XAxiDma_SimpleTransfer(), and XAxiDma_StartBdRingHw().

- -
-
- -
-
- - - - -
#define XAXIDMA_RX_CDESC0_MSB_OFFSET   0x00000044
-
- -

#include <xaxidma_hw.h>

- -

Rx Current Descriptor 0.

- -

Referenced by XAxiDma_UpdateBdRingCDesc().

- -
-
- -
-
- - - - -
#define XAXIDMA_RX_CDESC0_OFFSET   0x00000040
-
- -

#include <xaxidma_hw.h>

- -

Multi-Channel DMA Descriptor Offsets.

-

Rx Current Descriptor 0

- -

Referenced by XAxiDma_BdRingDumpRegs(), and XAxiDma_UpdateBdRingCDesc().

- -
-
- -
-
- - - - -
#define XAXIDMA_RX_NDESC_OFFSET   0x00000020
-
- -

#include <xaxidma_hw.h>

- -

Rx Next Descriptor Offset.

- -

Referenced by XAxiDma_BdRingDumpRegs(), XAxiDma_BdRingToHw(), XAxiDma_StartBdRingHw(), and XAxiDma_UpdateBdRingCDesc().

- -
-
- -
-
- - - - -
#define XAXIDMA_RX_OFFSET   0x00000030
-
- -

#include <xaxidma_hw.h>

- -

RX channel registers base offset.

- -

Referenced by XAxiDma_Busy(), XAxiDma_CfgInitialize(), XAxiDma_Reset(), XAxiDma_SelectCyclicMode(), and XAxiDma_SelectKeyHole().

- -
-
- -
-
- - - - -
#define XAXIDMA_RX_TDESC0_MSB_OFFSET   0x0000004C
-
- -

#include <xaxidma_hw.h>

- -

Rx Tail Descriptor 0.

- -

Referenced by XAxiDma_BdRingToHw(), and XAxiDma_StartBdRingHw().

- -
-
- -
-
- - - - -
#define XAXIDMA_RX_TDESC0_OFFSET   0x00000048
-
- -

#include <xaxidma_hw.h>

- -

Rx Tail Descriptor 0.

- -

Referenced by XAxiDma_BdRingDumpRegs(), XAxiDma_BdRingToHw(), and XAxiDma_StartBdRingHw().

- -
-
- -
-
- - - - -
#define XAXIDMA_SGCTL_OFFSET   0x0000002c
-
- -

#include <xaxidma_hw.h>

- -

SG Control Register.

- -
-
- -
-
- - - - -
#define XAXIDMA_SR_OFFSET   0x00000004
-
- -

#include <xaxidma_hw.h>

- -

Status.

- -

Referenced by XAxiDma_BdRingDumpRegs(), XAxiDma_Busy(), and XAxiDma_SimpleTransfer().

- -
-
- -
-
- - - - -
#define XAXIDMA_SRCADDR_MSB_OFFSET   0x0000001C
-
- -

#include <xaxidma_hw.h>

- -

Simple mode source address pointer.

- -

Referenced by XAxiDma_SimpleTransfer().

- -
-
- -
-
- - - - -
#define XAXIDMA_SRCADDR_OFFSET   0x00000018
-
- -

#include <xaxidma_hw.h>

- -

Simple mode source address pointer.

- -

Referenced by XAxiDma_SimpleTransfer().

- -
-
- -
-
- - - - -
#define XAXIDMA_TDESC_MSB_OFFSET   0x00000014
-
- -

#include <xaxidma_hw.h>

- -

Tail descriptor pointer.

- -

Referenced by XAxiDma_BdRingToHw(), and XAxiDma_StartBdRingHw().

- -
-
- -
-
- - - - -
#define XAXIDMA_TDESC_OFFSET   0x00000010
-
- -

#include <xaxidma_hw.h>

- -

Tail descriptor pointer.

- -

Referenced by XAxiDma_BdRingDumpRegs(), XAxiDma_BdRingToHw(), and XAxiDma_StartBdRingHw().

- -
-
- -
-
- - - - -
#define XAXIDMA_TX_OFFSET   0x00000000
-
- -

#include <xaxidma_hw.h>

- -

TX channel registers base offset.

- -

Referenced by XAxiDma_CfgInitialize(), and XAxiDma_Reset().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
#define XAxiDma_WriteReg( BaseAddress,
 RegOffset,
 Data 
)   XAxiDma_Out32((BaseAddress) + (RegOffset), (Data))
-
- -

#include <xaxidma_hw.h>

- -

Write the given register.

-
Parameters
- - - - -
BaseAddressis the base address of the device
RegOffsetis the register offset to be written
Datais the 32-bit value to write to the register
-
-
-
Returns
None.
-
Note
C-style signature: void XAxiDma_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data)
- -

Referenced by XAxiDma_BdRingSetCoalesce(), XAxiDma_BdRingToHw(), XAxiDma_Pause(), XAxiDma_Reset(), XAxiDma_SelectCyclicMode(), XAxiDma_SelectKeyHole(), XAxiDma_SimpleTransfer(), XAxiDma_StartBdRingHw(), and XAxiDma_UpdateBdRingCDesc().

- -
-
-

Typedef Documentation

- -
-
- - - - -
typedef struct XAxiDma XAxiDma
-
- -

#include <xaxidma.h>

- -

The XAxiDma driver instance data.

-

An instance must be allocated for each DMA engine in use.

- -
-
- -
-
- - - - -
typedef UINTPTR XAxiDma_Bd[XAXIDMA_BD_NUM_WORDS]
-
- -

#include <xaxidma_bd.h>

- -

The XAxiDma_Bd is the type for a buffer descriptor (BD).

- -
-
-

Function Documentation

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
u32 XAxiDma_BdGetAppWord (XAxiDma_BdBdPtr,
int Offset,
int * Valid 
)
-
- -

#include <xaxidma_bd.c>

- -

Get the APP word at the specified APP word offset for a BD.

-
Parameters
- - - - -
BdPtris the BD to operate on.
Offsetis the offset inside the APP word, it is valid from 0 to 4
Validis to tell the caller whether parameters are valid
-
-
-
Returns
The APP word. Passed in parameter Valid holds 0 for failure, and 1 for success.
-
Note
This function can be used only when DMA is in SG mode
- -

References XAXIDMA_BD_HAS_STSCNTRL_OFFSET, XAXIDMA_BD_USR0_OFFSET, and XAxiDma_BdRead.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int XAxiDma_BdRingAlloc (XAxiDma_BdRingRingPtr,
int NumBd,
XAxiDma_Bd ** BdSetPtr 
)
-
- -

#include <xaxidma_bdring.c>

- -

Reserve locations in the BD ring.

-

The set of returned BDs may be modified in preparation for future DMA transactions. Once the BDs are ready to be submitted to hardware, the application must call XAxiDma_BdRingToHw() in the same order which they were allocated here. Example:

-
-       NumBd = 2;
-       Status = XDsma_RingBdAlloc(MyRingPtr, NumBd, &MyBdSet);
       if (Status != XST_SUCCESS)
-       {
-           // Not enough BDs available for the request
-       }
       CurBd = MyBdSet;
-       for (i=0; i<NumBd; i++)
-       {
-           // Prepare CurBd.....
           // Onto next BD
-           CurBd = XAxiDma_BdRingNext(MyRingPtr, CurBd);
-       }
       // Give list to hardware
-       Status = XAxiDma_BdRingToHw(MyRingPtr, NumBd, MyBdSet);
-

A more advanced use of this function may allocate multiple sets of BDs. They must be allocated and given to hardware in the correct sequence:

-       // Legal
-       XAxiDma_BdRingAlloc(MyRingPtr, NumBd1, &MySet1);
-       XAxiDma_BdRingToHw(MyRingPtr, NumBd1, MySet1);
       // Legal
-       XAxiDma_BdRingAlloc(MyRingPtr, NumBd1, &MySet1);
-       XAxiDma_BdRingAlloc(MyRingPtr, NumBd2, &MySet2);
-       XAxiDma_BdRingToHw(MyRingPtr, NumBd1, MySet1);
-       XAxiDma_BdRingToHw(MyRingPtr, NumBd2, MySet2);
       // Not legal
-       XAxiDma_BdRingAlloc(MyRingPtr, NumBd1, &MySet1);
-       XAxiDma_BdRingAlloc(MyRingPtr, NumBd2, &MySet2);
-       XAxiDma_BdRingToHw(MyRingPtr, NumBd2, MySet2);
-       XAxiDma_BdRingToHw(MyRingPtr, NumBd1, MySet1);
-

Use the API defined in xaxidmabd.h to modify individual BDs. Traversal of the BD set can be done using XAxiDma_BdRingNext() and XAxiDma_BdRingPrev().

-
Parameters
- - - - -
RingPtris a pointer to the descriptor ring instance to be worked on.
NumBdis the number of BDs to allocate
BdSetPtris an output parameter, it points to the first BD available for modification.
-
-
-
Returns
    -
  • XST_SUCCESS if the requested number of BDs were returned in the BdSetPtr parameter.
  • -
  • XST_INVALID_PARAM if passed in NumBd is not positive
  • -
  • XST_FAILURE if there were not enough free BDs to satisfy the request.
  • -
-
-
Note
This function should not be preempted by another XAxiDma_BdRing function call that modifies the BD space. It is the caller's responsibility to provide a mutual exclusion mechanism.
-

Do not modify more BDs than the number requested with the NumBd parameter. Doing so will lead to data corruption and system instability.

-

This function can be used only when DMA is in SG mode

- -

References XAxiDma_BdRing::FreeCnt, XAxiDma_BdRing::FreeHead, and XAxiDma_BdRing::PreCnt.

- -
-
- -
-
- - - - - - - - -
int XAxiDma_BdRingCheck (XAxiDma_BdRingRingPtr)
-
- -

#include <xaxidma_bdring.c>

- -

Check the internal data structures of the BD ring for the provided channel.

-

The following checks are made:

-
    -
  • The BD ring is linked correctly in physical address space.
  • -
  • The internal pointers point to BDs in the ring.
  • -
  • The internal counters add up.
  • -
-

The channel should be stopped (through XAxiDma_Pause() or XAxiDma_Reset()) prior to calling this function.

-
Parameters
- - -
RingPtris a pointer to the descriptor ring to be worked on.
-
-
-
Returns
    -
  • XST_SUCCESS if no errors were found.
  • -
  • XST_DMA_SG_NO_LIST if the ring has not been created.
  • -
  • XST_IS_STARTED if the channel is not stopped.
  • -
  • XST_DMA_SG_LIST_ERROR if a problem is found with the internal data structures. If this value is returned, the channel should be reset,and the BD ring should be recreated through XAxiDma_BdRingCreate() to avoid data corruption or system instability.
  • -
-
-
Note
This function can be used only when DMA is in SG mode
- -

References XAxiDma_BdRing::AllCnt, XAxiDma_BdRing::FirstBdAddr, XAxiDma_BdRing::FirstBdPhysAddr, XAxiDma_BdRing::FreeCnt, XAxiDma_BdRing::FreeHead, XAxiDma_BdRing::HwCnt, XAxiDma_BdRing::HwHead, XAxiDma_BdRing::HwTail, XAxiDma_BdRing::LastBdAddr, XAxiDma_BdRing::PostCnt, XAxiDma_BdRing::PostHead, XAxiDma_BdRing::PreCnt, XAxiDma_BdRing::PreHead, XAxiDma_BdRing::RunState, XAxiDma_BdRing::Separation, XAXIDMA_BD_NDESC_OFFSET, and XAxiDma_BdRead.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
int XAxiDma_BdRingClone (XAxiDma_BdRingRingPtr,
XAxiDma_BdSrcBdPtr 
)
-
- -

#include <xaxidma_bdring.c>

- -

Clone the given BD into every BD in the ring.

-

Only the fields offset from XAXIDMA_BD_START_CLEAR are copied, for XAXIDMA_BD_BYTES_TO_CLEAR bytes. This covers: BufferAddr, Control/Buffer length, status, APP words 0 - 4, and software ID fields.

-

This function can be called only when all BDs are in the free group such as immediately after creation of the ring. This prevents modification of BDs while they are in use by hardware or the application.

-
Parameters
- - - -
RingPtris the BD ring instance to be worked on.
SrcBdPtris the source BD template to be cloned into the list.
-
-
-
Returns
    -
  • XST_SUCCESS if the list was modified.
  • -
  • XST_DMA_SG_NO_LIST if a list has not been created.
  • -
  • XST_DEVICE_IS_STARTED if the DMA channel has not been stopped.
  • -
  • XST_DMA_SG_LIST_ERROR if some of the BDs in this channel are under hardware or application control.
  • -
-
-
Note
This function can be used only when DMA is in SG mode
- -

References XAxiDma_BdRing::AllCnt, XAxiDma_BdRing::FirstBdAddr, XAxiDma_BdRing::FreeCnt, XAxiDma_BdRing::RunState, XAxiDma_BdRing::Separation, XAXIDMA_BD_BYTES_TO_CLEAR, XAXIDMA_BD_START_CLEAR, XAXIDMA_BD_STS_COMPLETE_MASK, XAXIDMA_BD_STS_OFFSET, XAxiDma_BdRead, and XAxiDma_BdWrite.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
u32 XAxiDma_BdRingCreate (XAxiDma_BdRingRingPtr,
UINTPTR PhysAddr,
UINTPTR VirtAddr,
u32 Alignment,
int BdCount 
)
-
- -

#include <xaxidma_bdring.c>

- -

Using a memory segment allocated by the caller, This fundtion creates and setup the BD ring.

-
Parameters
- - - - - - -
RingPtris the BD ring instance to be worked on.
PhysAddris the physical base address of application memory region.
VirtAddris the virtual base address of the application memory region.If address translation is not being utilized, then VirtAddr should be equivalent to PhysAddr.
Alignmentgoverns the byte alignment of individual BDs. This function will enforce a minimum alignment of XAXIDMA_BD_MINIMUM_ALIGNMENT bytes with no maximum as long as it is specified as a power of 2.
BdCountis the number of BDs to setup in the application memory region. It is assumed the region is large enough to contain the BDs.Refer to the "SGDMA Ring Creation" section in xaxidma.h for more information. The minimum valid value for this parameter is 1.
-
-
-
Returns
    -
  • XST_SUCCESS if initialization was successful
      -
    • XST_NO_FEATURE if the provided instance is a non SGDMA type of DMA channel.
    • -
    -
  • -
  • XST_INVALID_PARAM under any of the following conditions: 1) BdCount is not positive
  • -
-
-

2) PhysAddr and/or VirtAddr are not aligned to the given Alignment parameter;

-

3) Alignment parameter does not meet minimum requirements or is not a power of 2 value.

-
    -
  • XST_DMA_SG_LIST_ERROR if the memory segment containing the list spans over address 0x00000000 in virtual address space.
  • -
-
Note
This function can be used only when DMA is in SG mode
- -

References XAxiDma_BdRing::AllCnt, XAxiDma_BdRing::BdaRestart, XAxiDma_BdRing::FirstBdAddr, XAxiDma_BdRing::FirstBdPhysAddr, XAxiDma_BdRing::FreeCnt, XAxiDma_BdRing::FreeHead, XAxiDma_BdRing::HasStsCntrlStrm, XAxiDma_BdRing::HwCnt, XAxiDma_BdRing::HwHead, XAxiDma_BdRing::HwTail, XAxiDma_BdRing::LastBdAddr, XAxiDma_BdRing::Length, XAxiDma_BdRing::PostCnt, XAxiDma_BdRing::PostHead, XAxiDma_BdRing::PreCnt, XAxiDma_BdRing::PreHead, XAxiDma_BdRing::RunState, XAxiDma_BdRing::Separation, XAXIDMA_BD_ADDRLEN_OFFSET, XAXIDMA_BD_HAS_DRE_OFFSET, XAXIDMA_BD_HAS_DRE_SHIFT, XAXIDMA_BD_HAS_STSCNTRL_OFFSET, XAXIDMA_BD_MINIMUM_ALIGNMENT, XAXIDMA_BD_NDESC_MSB_OFFSET, XAXIDMA_BD_NDESC_OFFSET, XAxiDma_BdWrite, and XAXIDMA_DESC_LSB_MASK.

- -
-
- -
-
- - - - - - - - -
void XAxiDma_BdRingDumpRegs (XAxiDma_BdRingRingPtr)
-
- -

#include <xaxidma_bdring.c>

- -

Dump the registers for a channel.

-
Parameters
- - -
RingPtris a pointer to the descriptor ring to be worked on.
-
-
-
Returns
None
-
Note
This function can be used only when DMA is in SG mode
- -

References XAxiDma_BdRing::ChanBase, XAxiDma_BdRing::RingIndex, XAXIDMA_CDESC_OFFSET, XAXIDMA_CR_OFFSET, XAxiDma_ReadReg, XAXIDMA_RX_CDESC0_OFFSET, XAXIDMA_RX_NDESC_OFFSET, XAXIDMA_RX_TDESC0_OFFSET, XAXIDMA_SR_OFFSET, and XAXIDMA_TDESC_OFFSET.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int XAxiDma_BdRingFree (XAxiDma_BdRingRingPtr,
int NumBd,
XAxiDma_BdBdSetPtr 
)
-
- -

#include <xaxidma_bdring.c>

- -

Frees a set of BDs that had been previously retrieved with XAxiDma_BdRingFromHw().

-
Parameters
- - - - -
RingPtris a pointer to the descriptor ring instance to be worked on.
NumBdis the number of BDs to free.
BdSetPtris the head of a list of BDs returned by XAxiDma_BdRingFromHw().
-
-
-
Returns
    -
  • XST_SUCCESS if the set of BDs was freed.
  • -
  • XST_INVALID_PARAM if NumBd is negative
  • -
  • XST_DMA_SG_LIST_ERROR if this function was called out of sequence with XAxiDma_BdRingFromHw().
  • -
-
-
Note
This function should not be preempted by another XAxiDma function call that modifies the BD space. It is the caller's responsibility to ensure mutual exclusion.
-

This function can be used only when DMA is in SG mode

- -

References XAxiDma_BdRing::FreeCnt, XAxiDma_BdRing::PostCnt, and XAxiDma_BdRing::PostHead.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int XAxiDma_BdRingFromHw (XAxiDma_BdRingRingPtr,
int BdLimit,
XAxiDma_Bd ** BdSetPtr 
)
-
- -

#include <xaxidma_bdring.c>

- -

Returns a set of BD(s) that have been processed by hardware.

-

The returned BDs may be examined by the application to determine the outcome of the DMA transactions. Once the BDs have been examined, the application must call XAxiDma_BdRingFree() in the same order which they were retrieved here.

-

Example:

-
-       NumBd = XAxiDma_BdRingFromHw(MyRingPtr, XAXIDMA_ALL_BDS, &MyBdSet);
       if (NumBd == 0)
-       {
-          // hardware has nothing ready for us yet
-       }
       CurBd = MyBdSet;
-       for (i=0; i<NumBd; i++)
-       {
-          // Examine CurBd for post processing.....
          // Onto next BD
-          CurBd = XAxiDma_BdRingNext(MyRingPtr, CurBd);
-       }
       XAxiDma_BdRingFree(MyRingPtr, NumBd, MyBdSet); // Return the list
-

A more advanced use of this function may allocate multiple sets of BDs. They must be retrieved from hardware and freed in the correct sequence:

-       // Legal
-       XAxiDma_BdRingFromHw(MyRingPtr, NumBd1, &MySet1);
-       XAxiDma_BdRingFree(MyRingPtr, NumBd1, MySet1);
       // Legal
-       XAxiDma_BdRingFromHw(MyRingPtr, NumBd1, &MySet1);
-       XAxiDma_BdRingFromHw(MyRingPtr, NumBd2, &MySet2);
-       XAxiDma_BdRingFree(MyRingPtr, NumBd1, MySet1);
-       XAxiDma_BdRingFree(MyRingPtr, NumBd2, MySet2);
       // Not legal
-       XAxiDma_BdRingFromHw(MyRingPtr, NumBd1, &MySet1);
-       XAxiDma_BdRingFromHw(MyRingPtr, NumBd2, &MySet2);
-       XAxiDma_BdRingFree(MyRingPtr, NumBd2, MySet2);
-       XAxiDma_BdRingFree(MyRingPtr, NumBd1, MySet1);
-

If hardware has partially completed a packet spanning multiple BDs, then none of the BDs for that packet will be included in the results.

-
Parameters
- - - - -
RingPtris a pointer to the descriptor ring instance to be worked on.
BdLimitis the maximum number of BDs to return in the set. Use XAXIDMA_ALL_BDS to return all BDs that have been processed.
BdSetPtris an output parameter, it points to the first BD available for examination.
-
-
-
Returns
The number of BDs processed by hardware. A value of 0 indicates that no data is available. No more than BdLimit BDs will be returned.
-
Note
Treat BDs returned by this function as read-only.
-

This function should not be preempted by another XAxiDma ring function call that modifies the BD space. It is the caller's responsibility to provide a mutual exclusion mechanism.

-

This function can be used only when DMA is in SG mode

- -

References XAxiDma_BdRing::HwCnt, XAxiDma_BdRing::HwHead, XAxiDma_BdRing::HwTail, XAxiDma_BdRing::IsRxChannel, XAxiDma_BdRing::PostCnt, XAXIDMA_BD_CTRL_LEN_OFFSET, XAXIDMA_BD_CTRL_TXEOF_MASK, XAXIDMA_BD_STS_COMPLETE_MASK, XAXIDMA_BD_STS_OFFSET, XAXIDMA_BD_STS_RXEOF_MASK, XAxiDma_BdRead, and XAxiDma_BdRingNext.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void XAxiDma_BdRingGetCoalesce (XAxiDma_BdRingRingPtr,
u32 * CounterPtr,
u32 * TimerPtr 
)
-
- -

#include <xaxidma_bdring.c>

- -

Retrieve current interrupt coalescing parameters from the given descriptor ring channel.

-
Parameters
- - - - -
RingPtris a pointer to the descriptor ring instance to be worked on.
CounterPtrpoints to a memory location where the current packet counter will be written.
TimerPtrpoints to a memory location where the current waitbound timer will be written.
-
-
-
Returns
The passed in parameters, CounterPtr and TimerPtr, holds the references to the return values.
-
Note
This function can be used only when DMA is in SG mode
- -

References XAxiDma_BdRing::ChanBase, XAXIDMA_COALESCE_MASK, XAXIDMA_CR_OFFSET, XAXIDMA_DELAY_MASK, and XAxiDma_ReadReg.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int XAxiDma_BdRingSetCoalesce (XAxiDma_BdRingRingPtr,
u32 Counter,
u32 Timer 
)
-
- -

#include <xaxidma_bdring.c>

- -

Set interrupt coalescing parameters for the given descriptor ring channel.

-
Parameters
- - - - -
RingPtris a pointer to the descriptor ring instance to be worked on.
Countersets the packet counter on the channel. Valid range is
    -
  • 1..255.
  • -
  • XAXIDMA_NO_CHANGE to leave this setting unchanged.
  • -
-
Timersets the waitbound timer on the channel. Valid range is
    -
  • 0..255.
  • -
-
-
-
-
    -
  • XAXIDMA_NO_CHANGE to leave this setting unchanged. Each unit depend on hardware building parameter C_DLYTMR_RESOLUTION,which is in the range from 0 to 100,000 clock cycles. A value of 0 disables the delay interrupt.
  • -
-
Returns
    -
  • XST_SUCCESS if interrupt coalescing settings updated
  • -
  • XST_FAILURE if Counter or Timer parameters are out of range
  • -
-
-
Note
This function can be used only when DMA is in SG mode
- -

References XAxiDma_BdRing::ChanBase, XAXIDMA_COALESCE_MASK, XAXIDMA_CR_OFFSET, XAXIDMA_DELAY_MASK, XAxiDma_ReadReg, and XAxiDma_WriteReg.

- -
-
- -
-
- - - - - - - - -
int XAxiDma_BdRingStart (XAxiDma_BdRingRingPtr)
-
- -

#include <xaxidma_bdring.c>

- -

Start a DMA channel, updates current descriptors and Allow DMA transactions to commence on a given channel if descriptors are ready to be processed.

-

After a DMA channel is started, it is not halted, and it is idle (no active DMA transfers).

-
Parameters
- - -
RingPtris the Channel instance to be worked on
-
-
-
Returns
    -
  • XST_SUCCESS upon success
  • -
  • XST_DMA_ERROR if no valid BD available to put into current BD register
  • -
-
-
Note
This function can be used only when DMA is in SG mode
- -

References XAxiDma_StartBdRingHw(), and XAxiDma_UpdateBdRingCDesc().

- -

Referenced by XAxiDma_Resume().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int XAxiDma_BdRingToHw (XAxiDma_BdRingRingPtr,
int NumBd,
XAxiDma_BdBdSetPtr 
)
-
- -

#include <xaxidma_bdring.c>

- -

Enqueue a set of BDs to hardware that were previously allocated by XAxiDma_BdRingAlloc().

-

Once this function returns, the argument BD set goes under hardware control. Changes to these BDs should be held until they are finished by hardware to avoid data corruption and system instability.

-

For transmit, the set will be rejected if the last BD of the set does not mark the end of a packet or the first BD does not mark the start of a packet.

-
Parameters
- - - - -
RingPtris a pointer to the descriptor ring instance to be worked on.
NumBdis the number of BDs in the set.
BdSetPtris the first BD of the set to commit to hardware.
-
-
-
Returns
    -
  • XST_SUCCESS if the set of BDs was accepted and enqueued to hardware
  • -
  • XST_INVALID_PARAM if passed in NumBd is negative
  • -
  • XST_FAILURE if the set of BDs was rejected because the first BD does not have its start-of-packet bit set, or the last BD does not have its end-of-packet bit set, or any one of the BDs has 0 length.
  • -
  • XST_DMA_SG_LIST_ERROR if this function was called out of sequence with XAxiDma_BdRingAlloc()
  • -
-
-
Note
This function should not be preempted by another XAxiDma ring function call that modifies the BD space. It is the caller's responsibility to provide a mutual exclusion mechanism.
-

This function can be used only when DMA is in SG mode

- -

References XAxiDma_BdRing::ChanBase, XAxiDma_BdRing::HwCnt, XAxiDma_BdRing::HwTail, XAxiDma_BdRing::IsRxChannel, XAxiDma_BdRing::PreCnt, XAxiDma_BdRing::PreHead, XAxiDma_BdRing::RingIndex, XAxiDma_BdRing::RunState, XAXIDMA_BD_CTRL_LEN_OFFSET, XAXIDMA_BD_CTRL_TXEOF_MASK, XAXIDMA_BD_CTRL_TXSOF_MASK, XAXIDMA_BD_STS_COMPLETE_MASK, XAXIDMA_BD_STS_OFFSET, XAxiDma_BdGetCtrl, XAxiDma_BdGetLength, XAxiDma_BdGetSts, XAxiDma_BdRead, XAxiDma_BdRingNext, XAxiDma_BdWrite, XAXIDMA_DESC_LSB_MASK, XAXIDMA_RX_NDESC_OFFSET, XAXIDMA_RX_TDESC0_MSB_OFFSET, XAXIDMA_RX_TDESC0_OFFSET, XAXIDMA_TDESC_MSB_OFFSET, XAXIDMA_TDESC_OFFSET, and XAxiDma_WriteReg.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int XAxiDma_BdRingUnAlloc (XAxiDma_BdRingRingPtr,
int NumBd,
XAxiDma_BdBdSetPtr 
)
-
- -

#include <xaxidma_bdring.c>

- -

Fully or partially undo an XAxiDma_BdRingAlloc() operation.

-

Use this function if all the BDs allocated by XAxiDma_BdRingAlloc() could not be transferred to hardware with XAxiDma_BdRingToHw().

-

This function releases the BDs after they have been allocated but before they have been given to hardware.

-

This function is not the same as XAxiDma_BdRingFree(). The Free function returns BDs to the free list after they have been processed by hardware, while UnAlloc returns them before being processed by hardware.

-

There are two scenarios where this function can be used. Full UnAlloc or Partial UnAlloc. A Full UnAlloc means all the BDs Alloc'd will be returned:

-
-   Status = XAxiDma_BdRingAlloc(MyRingPtr, 10, &BdPtr);
-       ...
-       ...
-   if (Error)
-   {
-       Status = XAxiDma_BdRingUnAlloc(MyRingPtr, 10, &BdPtr);
-   }
-

A partial UnAlloc means some of the BDs Alloc'd will be returned:

-
-   Status = XAxiDma_BdRingAlloc(MyRingPtr, 10, &BdPtr);
-   BdsLeft = 10;
-   CurBdPtr = BdPtr;
   while (BdsLeft)
-   {
-      if (Error)
-      {
-         Status = XAxiDma_BdRingUnAlloc(MyRingPtr, BdsLeft, CurBdPtr);
-      }
      CurBdPtr = XAxiDma_BdRingNext(MyRingPtr, CurBdPtr);
-      BdsLeft--;
-   }
-

A partial UnAlloc must include the last BD in the list that was Alloc'd.

-
Parameters
- - - - -
RingPtris a pointer to the descriptor ring instance to be worked on.
NumBdis the number of BDs to unallocate
BdSetPtrpoints to the first of the BDs to be returned.
-
-
-
Returns
    -
  • XST_SUCCESS if the BDs were unallocated.
  • -
  • XST_INVALID_PARAM if passed in NumBd is negative
  • -
  • XST_FAILURE if NumBd parameter was greater that the number of BDs in the preprocessing state.
  • -
-
-
Note
This function should not be preempted by another XAxiDma ring function call that modifies the BD space. It is the caller's responsibility to provide a mutual exclusion mechanism.
-

This function can be used only when DMA is in SG mode

- -

References XAxiDma_BdRing::FreeCnt, XAxiDma_BdRing::FreeHead, and XAxiDma_BdRing::PreCnt.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int XAxiDma_BdSetAppWord (XAxiDma_BdBdPtr,
int Offset,
u32 Word 
)
-
- -

#include <xaxidma_bd.c>

- -

Set the APP word at the specified APP word offset for a BD.

-
Parameters
- - - - -
BdPtris the BD to operate on.
Offsetis the offset inside the APP word, it is valid from 0 to 4
Wordis the value to set
-
-
-
Returns
    -
  • XST_SUCCESS for success
  • -
  • XST_INVALID_PARAM under following error conditions: 1) StsCntrlStrm is not built in hardware 2) Offset is not in valid range
  • -
-
-
Note
If the hardware build has C_SG_USE_STSAPP_LENGTH set to 1, then the last APP word, XAXIDMA_LAST_APPWORD, must have non-zero value when AND with 0x7FFFFF. Not doing so will cause the hardware to stall. This function can be used only when DMA is in SG mode
- -

References XAXIDMA_BD_HAS_STSCNTRL_OFFSET, XAXIDMA_BD_USR0_OFFSET, XAxiDma_BdRead, and XAxiDma_BdWrite.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
u32 XAxiDma_BdSetBufAddr (XAxiDma_BdBdPtr,
UINTPTR Addr 
)
-
- -

#include <xaxidma_bd.c>

- -

Set the BD's buffer address.

-
Parameters
- - - -
BdPtris the BD to operate on
Addris the address to set
-
-
-
Returns
    -
  • XST_SUCCESS if buffer address set successfully
  • -
  • XST_INVALID_PARAM if hardware has no DRE and address is not aligned
  • -
-
-
Note
This function can be used only when DMA is in SG mode
- -

References XAXIDMA_BD_ADDRLEN_OFFSET, XAXIDMA_BD_BUFA_MSB_OFFSET, XAXIDMA_BD_BUFA_OFFSET, XAXIDMA_BD_HAS_DRE_MASK, XAXIDMA_BD_HAS_DRE_OFFSET, XAXIDMA_BD_WORDLEN_MASK, XAxiDma_BdRead, and XAxiDma_BdWrite.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
u32 XAxiDma_BdSetBufAddrMicroMode (XAxiDma_BdBdPtr,
UINTPTR Addr 
)
-
- -

#include <xaxidma_bd.c>

- -

Set the BD's buffer address when configured for Micro Mode.

-

The buffer address should be 4K aligned.

-
Parameters
- - - -
BdPtris the BD to operate on
Addris the address to set
-
-
-
Returns
    -
  • XST_SUCCESS if buffer address set successfully
  • -
  • XST_INVALID_PARAM if hardware has no DRE and address is not aligned
  • -
-
-
Note
This function can be used only when DMA is in SG mode
- -

References XAXIDMA_BD_ADDRLEN_OFFSET, XAXIDMA_BD_BUFA_MSB_OFFSET, XAXIDMA_BD_BUFA_OFFSET, XAxiDma_BdRead, XAxiDma_BdWrite, and XAXIDMA_MICROMODE_MIN_BUF_ALIGN.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
void XAxiDma_BdSetCtrl (XAxiDma_BdBdPtr,
u32 Data 
)
-
- -

#include <xaxidma_bd.c>

- -

Set the control bits for a BD.

-
Parameters
- - - -
BdPtris the BD to operate on.
Datais the bit value to set
-
-
-
Returns
None
-
Note
This function can be used only when DMA is in SG mode
- -

References XAXIDMA_BD_CTRL_ALL_MASK, XAXIDMA_BD_CTRL_LEN_OFFSET, XAxiDma_BdRead, and XAxiDma_BdWrite.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int XAxiDma_BdSetLength (XAxiDma_BdBdPtr,
u32 LenBytes,
u32 LengthMask 
)
-
- -

#include <xaxidma_bd.c>

- -

Set the length field for the given BD.

-

Length has to be non-zero and less than LengthMask.

-

For TX channels, the value passed in should be the number of bytes to transmit from the TX buffer associated with the given BD.

-

For RX channels, the value passed in should be the size of the RX buffer associated with the given BD in bytes. This is to notify the RX channel the capability of the RX buffer to avoid buffer overflow.

-

The actual receive length can be equal or smaller than the specified length. The actual transfer length will be updated by the hardware in the XAXIDMA_BD_STS_OFFSET word in the BD.

-
Parameters
- - - - -
BdPtris the BD to operate on.
LenBytesis the requested transfer length
LengthMaskis the maximum transfer length
-
-
-
Returns
    -
  • XST_SUCCESS for success
  • -
  • XST_INVALID_PARAM for invalid BD length
  • -
-
-
Note
This function can be used only when DMA is in SG mode
- -

References XAXIDMA_BD_CTRL_LEN_OFFSET, XAxiDma_BdRead, and XAxiDma_BdWrite.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
u32 XAxiDma_Busy (XAxiDmaInstancePtr,
int Direction 
)
-
- -

#include <xaxidma.c>

- -

This function checks whether specified DMA channel is busy.

-
Parameters
- - - -
InstancePtris the driver instance we are working on
Directionis DMA transfer direction, valid values are
    -
  • XAXIDMA_DMA_TO_DEVICE.
  • -
  • XAXIDMA_DEVICE_TO_DMA.
  • -
-
-
-
-
Returns
- TRUE if channel is busy
    -
  • FALSE if channel is idle
  • -
-
-
Note
None.
- -

References XAXIDMA_IDLE_MASK, XAxiDma_ReadReg, XAXIDMA_RX_OFFSET, and XAXIDMA_SR_OFFSET.

- -

Referenced by XAxiDma_SimpleTransfer().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
int XAxiDma_CfgInitialize (XAxiDmaInstancePtr,
XAxiDma_ConfigConfig 
)
-
- -

#include <xaxidma.c>

- -

This function initializes a DMA engine.

-

This function must be called prior to using a DMA engine. Initializing a engine includes setting up the register base address, setting up the instance data, and ensuring the hardware is in a quiescent state.

-
Parameters
- - - -
InstancePtris a pointer to the DMA engine instance to be worked on.
Configis a pointer to an XAxiDma_Config structure. It contains the information about the hardware build, including base address,and whether status control stream (StsCntrlStrm), MM2S and S2MM are included in the build.
-
-
-
Returns
    -
  • XST_SUCCESS for successful initialization
  • -
  • XST_INVALID_PARAM if pointer to the configuration structure is NULL
  • -
  • XST_DMA_ERROR if reset operation failed at the end of initialization
  • -
-
-
Note
We assume the hardware building tool will check and error out for a hardware build that has no transfer channels.
- -

References XAxiDma::AddrWidth, XAxiDma_Config::AddrWidth, XAxiDma_BdRing::ChanBase, XAxiDma_BdRing::HasStsCntrlStrm, XAxiDma_BdRing::IsRxChannel, XAxiDma_BdRing::RingIndex, XAxiDma_BdRing::RunState, XAxiDma_Reset(), XAxiDma_ResetIsDone(), XAXIDMA_RX_OFFSET, and XAXIDMA_TX_OFFSET.

- -
-
- -
-
- - - - - - - - -
void XAxiDma_DumpBd (XAxiDma_BdBdPtr)
-
-
- -
-
- - - - - - - - -
XAxiDma_Config * XAxiDma_LookupConfig (u32 DeviceId)
-
- -

#include <xaxidma.h>

- -

Look up the hardware configuration for a device instance.

-
Parameters
- - -
DeviceIdis the unique device ID of the device to lookup for
-
-
-
Returns
The configuration structure for the device. If the device ID is not found,a NULL pointer is returned.
-
Note
None
- -
-
- -
-
- - - - - - - - -
int XAxiDma_Pause (XAxiDmaInstancePtr)
-
- -

#include <xaxidma.c>

- -

Pause DMA transactions on both channels.

-

If the engine is running and doing transfers, this function does not stop the DMA transactions immediately, because then hardware will throw away our previously queued transfers. All submitted transfers will finish. Transfers submitted after this function will not start until XAxiDma_BdRingStart() or XAxiDma_Resume() is called.

-
Parameters
- - -
InstancePtris a pointer to the DMA engine instance to be worked on.
-
-
-
Returns
    -
  • XST_SUCCESS if successful
  • -
  • XST_NOT_SGDMA, if the driver instance is not initialized
  • -
-
-
Note
None
- -

References XAxiDma_BdRing::ChanBase, XAxiDma_BdRing::RunState, XAXIDMA_CR_OFFSET, XAXIDMA_CR_RUNSTOP_MASK, XAxiDma_GetRxIndexRing, XAxiDma_GetTxRing, XAxiDma_HasSg, XAxiDma_ReadReg, and XAxiDma_WriteReg.

- -
-
- -
-
- - - - - - - - -
void XAxiDma_Reset (XAxiDmaInstancePtr)
-
- -

#include <xaxidma.c>

- -

Reset both TX and RX channels of a DMA engine.

-

Reset one channel resets the whole AXI DMA engine.

-

Any DMA transaction in progress will finish gracefully before engine starts reset. Any other transactions that have been submitted to hardware will be discarded by the hardware.

-
Parameters
- - -
InstancePtris a pointer to the DMA engine instance to be worked on.
-
-
-
Returns
None
-
Note
After the reset:
    -
  • All interrupts are disabled.
  • -
  • Engine is halted
  • -
-
- -

References XAxiDma_BdRing::RunState, XAxiDma_BdRingSnapShotCurrBd, XAXIDMA_CR_OFFSET, XAXIDMA_CR_RESET_MASK, XAxiDma_GetRxIndexRing, XAxiDma_GetTxRing, XAxiDma_HasSg, XAXIDMA_RX_OFFSET, XAXIDMA_TX_OFFSET, and XAxiDma_WriteReg.

- -

Referenced by XAxiDma_CfgInitialize(), and XAxiDma_Selftest().

- -
-
- -
-
- - - - - - - - -
int XAxiDma_ResetIsDone (XAxiDmaInstancePtr)
-
- -

#include <xaxidma.c>

- -

Check whether reset is done.

-
Parameters
- - -
InstancePtris a pointer to the DMA engine instance to be worked on.
-
-
-
Returns
    -
  • 1 if reset is done.
  • -
-
-
    -
  • 0 if reset is not done
  • -
-
Note
None
- -

References XAxiDma_BdRing::ChanBase, XAXIDMA_CR_OFFSET, XAXIDMA_CR_RESET_MASK, XAxiDma_GetRxRing, XAxiDma_GetTxRing, and XAxiDma_ReadReg.

- -

Referenced by XAxiDma_CfgInitialize(), and XAxiDma_Selftest().

- -
-
- -
-
- - - - - - - - -
int XAxiDma_Resume (XAxiDmaInstancePtr)
-
- -

#include <xaxidma.c>

- -

Resume DMA transactions on both channels.

-
Parameters
- - -
InstancePtris a pointer to the DMA engine instance to be worked on.
-
-
-
Returns
    -
  • XST_SUCCESS for success
  • -
  • XST_NOT_SGDMA if the driver instance has not been initialized
  • -
  • XST_DMA_ERROR if one of the channels fails to start
  • -
-
-
Note
None
- -

References XAxiDma_BdRing::RunState, XAxiDma_BdRingStart(), XAxiDma_GetRxIndexRing, XAxiDma_GetTxRing, and XAxiDma_HasSg.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int XAxiDma_SelectCyclicMode (XAxiDmaInstancePtr,
int Direction,
int Select 
)
-
- -

#include <xaxidma.c>

- -

This function Enable or Disable Cyclic Mode Feature.

-
Parameters
- - - -
InstancePtris the driver instance we are working on
Directionis DMA transfer direction, valid values are
    -
  • XAXIDMA_DMA_TO_DEVICE.
  • -
  • XAXIDMA_DEVICE_TO_DMA. Select is the option to enable (TRUE) or disable (FALSE).
  • -
-
-
-
-
Returns
- XST_SUCCESS for success
-
Note
None.
- -

References XAXIDMA_CR_CYCLIC_MASK, XAXIDMA_CR_OFFSET, XAxiDma_ReadReg, XAXIDMA_RX_OFFSET, and XAxiDma_WriteReg.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int XAxiDma_SelectKeyHole (XAxiDmaInstancePtr,
int Direction,
int Select 
)
-
- -

#include <xaxidma.c>

- -

This function Enable or Disable KeyHole Feature.

-
Parameters
- - - -
InstancePtris the driver instance we are working on
Directionis DMA transfer direction, valid values are
    -
  • XAXIDMA_DMA_TO_DEVICE.
  • -
  • XAXIDMA_DEVICE_TO_DMA. Select is the option to enable (TRUE) or disable (FALSE).
  • -
-
-
-
-
Returns
- XST_SUCCESS for success
-
Note
None.
- -

References XAXIDMA_CR_KEYHOLE_MASK, XAXIDMA_CR_OFFSET, XAxiDma_ReadReg, XAXIDMA_RX_OFFSET, and XAxiDma_WriteReg.

- -
-
- -
-
- - - - - - - - -
int XAxiDma_Selftest (XAxiDmaInstancePtr)
-
- -

#include <xaxidma.h>

- -

Runs a self-test on the driver/device.

-

This test perform a reset of the DMA device and checks the device is coming out of reset or not

-
Parameters
- - -
InstancePtris a pointer to the XAxiDma instance.
-
-
-
Returns
    -
  • XST_SUCCESS if self-test was successful
  • -
-
-
    -
  • XST_FAILURE if the device is not coming out of reset.
  • -
-
Note
None.
- -

References XAxiDma_Reset(), and XAxiDma_ResetIsDone().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
u32 XAxiDma_SimpleTransfer (XAxiDmaInstancePtr,
UINTPTR BuffAddr,
u32 Length,
int Direction 
)
-
- -

#include <xaxidma.c>

- -

This function does one simple transfer submission.

-

It checks in the following sequence:

    -
  • if engine is busy, cannot submit
  • -
  • if engine is in SG mode , cannot submit
  • -
-
Parameters
- - - - - -
InstancePtris the pointer to the driver instance
BuffAddris the address of the source/destination buffer
Lengthis the length of the transfer
Directionis DMA transfer direction, valid values are
    -
  • XAXIDMA_DMA_TO_DEVICE.
  • -
  • XAXIDMA_DEVICE_TO_DMA.
  • -
-
-
-
-
Returns
    -
  • XST_SUCCESS for success of submission
  • -
  • XST_FAILURE for submission failure, maybe caused by: Another simple transfer is still going
  • -
  • XST_INVALID_PARAM if:Length out of valid range [1:8M] Or, address not aligned when DRE is not built in
  • -
-
-
Note
This function is used only when system is configured as Simple mode.
- -

References XAxiDma::AddrWidth, XAxiDma_BdRing::ChanBase, XAXIDMA_BUFFLEN_OFFSET, XAxiDma_Busy(), XAXIDMA_CR_OFFSET, XAXIDMA_CR_RUNSTOP_MASK, XAXIDMA_DESTADDR_MSB_OFFSET, XAXIDMA_DESTADDR_OFFSET, XAXIDMA_HALTED_MASK, XAxiDma_HasSg, XAXIDMA_MICROMODE_MIN_BUF_ALIGN, XAxiDma_ReadReg, XAXIDMA_SR_OFFSET, XAXIDMA_SRCADDR_MSB_OFFSET, XAXIDMA_SRCADDR_OFFSET, and XAxiDma_WriteReg.

- -
-
- -
-
- - - - - - - - -
int XAxiDma_StartBdRingHw (XAxiDma_BdRingRingPtr)
-
- -

#include <xaxidma_bdring.c>

- -

Start a DMA channel and Allow DMA transactions to commence on a given channel if descriptors are ready to be processed.

-

After a DMA channel is started, it is not halted, and it is idle (no active DMA transfers).

-
Parameters
- - -
RingPtris the Channel instance to be worked on
-
-
-
Returns
    -
  • XST_SUCCESS upon success
  • -
  • XST_DMA_ERROR if no valid BD available to put into current BD register
  • -
-
-
Note
This function can be used only when DMA is in SG mode
- -

References XAxiDma_BdRing::ChanBase, XAxiDma_BdRing::HwCnt, XAxiDma_BdRing::HwTail, XAxiDma_BdRing::IsRxChannel, XAxiDma_BdRing::RingIndex, XAxiDma_BdRing::RunState, XAXIDMA_BD_STS_COMPLETE_MASK, XAXIDMA_BD_STS_OFFSET, XAxiDma_BdRead, XAxiDma_BdRingHwIsStarted, XAXIDMA_CR_OFFSET, XAXIDMA_CR_RUNSTOP_MASK, XAXIDMA_DESC_LSB_MASK, XAxiDma_ReadReg, XAXIDMA_RX_NDESC_OFFSET, XAXIDMA_RX_TDESC0_MSB_OFFSET, XAXIDMA_RX_TDESC0_OFFSET, XAXIDMA_TDESC_MSB_OFFSET, XAXIDMA_TDESC_OFFSET, and XAxiDma_WriteReg.

- -

Referenced by XAxiDma_BdRingStart().

- -
-
- -
-
- - - - - - - - -
int XAxiDma_UpdateBdRingCDesc (XAxiDma_BdRingRingPtr)
-
- -

#include <xaxidma_bdring.c>

- -

Update Current Descriptor.

-
Parameters
- - -
RingPtris the Channel instance to be worked on
-
-
-
Returns
    -
  • XST_SUCCESS upon success
  • -
  • XST_DMA_ERROR if no valid BD available to put into current BD register
  • -
-
-
Note
This function can be used only when DMA is in SG mode
- -

References XAxiDma_BdRing::AllCnt, XAxiDma_BdRing::BdaRestart, XAxiDma_BdRing::ChanBase, XAxiDma_BdRing::IsRxChannel, XAxiDma_BdRing::RingIndex, XAxiDma_BdRing::RunState, XAxiDma_BdHwCompleted, XAxiDma_BdRingHwIsStarted, XAxiDma_BdRingNext, XAXIDMA_CDESC_MSB_OFFSET, XAXIDMA_CDESC_OFFSET, XAXIDMA_DESC_LSB_MASK, XAXIDMA_RX_CDESC0_MSB_OFFSET, XAXIDMA_RX_CDESC0_OFFSET, XAXIDMA_RX_NDESC_OFFSET, and XAxiDma_WriteReg.

- -

Referenced by XAxiDma_BdRingStart().

- -
-
-
- - - diff --git a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/index.html b/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/index.html deleted file mode 100644 index b6e8d3690..000000000 --- a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/index.html +++ /dev/null @@ -1,261 +0,0 @@ - - - - - - -axidma_v9_0: Main Page - - - - - - - -
-
- - - - - - - -
-
axidma_v9_0 -
-
Xilinx SDK Drivers API Documentation
-
-
- - - -
-
-
-
axidma_v9_0 Documentation
-
-
-

This is the driver API for the AXI DMA engine.For a full description of DMA features, please see the hardware spec. This driver supports the following features:

-
    -
  • Scatter-Gather DMA (SGDMA)
  • -
  • Simple DMA
  • -
  • Interrupts
  • -
  • Programmable interrupt coalescing for SGDMA
  • -
  • APIs to manage Buffer Descriptors (BD) movement to and from the SGDMA engine
  • -
-

Simple DMA

-

Simple DMA allows the application to define a single transaction between DMA and Device. It has two channels: one from the DMA to Device and the other from Device to DMA. Application has to set the buffer address and length fields to initiate the transfer in respective channel.

-

Transactions

-

The object used to describe a transaction is referred to as a Buffer Descriptor (BD). Buffer descriptors are allocated in the user application. The user application needs to set buffer address, transfer length, and control information for this transfer. The control information includes SOF and EOF. Definition of those masks are in xaxidma_hw.h

-

Scatter-Gather DMA

-

SGDMA allows the application to define a list of transactions in memory which the hardware will process without further application intervention. During this time, the application is free to continue adding more work to keep the Hardware busy.

-

User can check for the completion of transactions through polling the hardware, or interrupts.

-

SGDMA processes whole packets. A packet is defined as a series of data bytes that represent a message. SGDMA allows a packet of data to be broken up into one or more transactions. For example, take an Ethernet IP packet which consists of a 14 byte header followed by a 1 or more bytes of payload. With SGDMA, the application may point a BD to the header and another BD to the payload, then transfer them as a single message. This strategy can make a TCP/IP stack more efficient by allowing it to keep packet header and data in different memory regions instead of assembling packets into contiguous blocks of memory.

-

BD Ring Management

-

BD rings are shared by the software and the hardware.

-

The hardware expects BDs to be setup as a linked list. The DMA hardware walks through the list by following the next pointer field of a completed BD. The hardware stops processing when the just completed BD is the same as the BD specified in the Tail Ptr register in the hardware.

-

The last BD in the ring is linked to the first BD in the ring.

-

All BD management are done inside the driver. The user application should not directly modify the BD fields. Modifications to the BD fields should always go through the specific API functions.

-

Within the ring, the driver maintains four groups of BDs. Each group consists of 0 or more adjacent BDs:

-
    -
  • Free: The BDs that can be allocated by the application with XAxiDma_BdRingAlloc().
  • -
  • Pre-process: The BDs that have been allocated with XAxiDma_BdRingAlloc(). These BDs are under application control. The application modifies these BDs through driver API to prepare them for DMA transactions.
  • -
  • Hardware: The BDs that have been enqueued to hardware with XAxiDma_BdRingToHw(). These BDs are under hardware control and may be in a state of awaiting hardware processing, in process, or processed by hardware. It is considered an error for the application to change BDs while they are in this group. Doing so can cause data corruption and lead to system instability.
  • -
  • Post-process: The BDs that have been processed by hardware and have been extracted from the Hardware group with XAxiDma_BdRingFromHw(). These BDs are under application control. The application can check the transfer status of these BDs. The application use XAxiDma_BdRingFree() to put them into the Free group.
  • -
-

BDs are expected to transition in the following way for continuous DMA transfers:

        XAxiDma_BdRingAlloc()                   XAxiDma_BdRingToHw()
-  Free ------------------------> Pre-process ----------------------> Hardware
-                                                                     |
-   /|\                                                               |
-    |   XAxiDma_BdRingFree()                  XAxiDma_BdRingFromHw() |
-    +--------------------------- Post-process <----------------------+

When a DMA transfer is to be cancelled before enqueuing to hardware, application can return the requested BDs to the Free group using XAxiDma_BdRingUnAlloc(), as shown below:

        XAxiDma_BdRingUnAlloc()
-  Free <----------------------- Pre-process

The API provides functions for BD list traversal:

-

These functions should be used with care as they do not understand where one group ends and another begins.

-

SGDMA Descriptor Ring Creation

-

BD ring is created using XAxiDma_BdRingCreate(). The memory for the BD ring is allocated by the application, and it has to be contiguous. Physical address is required to setup the BD ring.

-

The applicaiton can use XAxiDma_BdRingMemCalc() to find out the amount of memory needed for a certain number of BDs. XAxiDma_BdRingCntCalc() can be used to find out how many BDs can be allocated for certain amount of memory.

-

A helper function, XAxiDma_BdRingClone(), can speed up the BD ring setup if the BDs have same types of controls, for example, SOF and EOF. After using the XAxiDma_BdRingClone(), the application only needs to setup the buffer address and transfer length. Note that certain BDs in one packet, for example, the first BD and the last BD, may need to setup special control information.

-

Descriptor Ring State Machine

-

There are two states of the BD ring:

-
    -
  • HALTED (H), where hardware is not running
  • -
  • NOT HALTED (NH), where hardware is running
  • -
-

The following diagram shows the state transition for the DMA engine:

-
-  _____ XAxiDma_StartBdRingHw(), or XAxiDma_BdRingStart(),   ______
-  |   |               or XAxiDma_Resume()                    |    |
-  | H |----------------------------------------------------->| NH |
-  |   |<-----------------------------------------------------|    |
-  -----   XAxiDma_Pause() or XAxiDma_Reset()                 ------
-

Interrupt Coalescing

-

SGDMA provides control over the frequency of interrupts through interrupt coalescing. The DMA engine provides two ways to tune the interrupt coalescing:

-
    -
  • The packet threshold counter. Interrupt will fire once the programmable number of packets have been processed by the engine.
  • -
  • The packet delay timer counter. Interrupt will fire once the programmable amount of time has passed after processing the last packet, and no new packets to process. Note that the interrupt will only fire if at least one packet has been processed.
  • -
-

Interrupt

-

Interrupts are handled by the user application. Each DMA channel has its own interrupt ID. The driver provides APIs to enable/disable interrupt, and tune the interrupt frequency regarding to packet processing frequency.

-

Software Initialization

-

To use the Simple mode DMA engine for transfers, the following setup is required:

-
    -
  • DMA Initialization using XAxiDma_CfgInitialize() function. This step initializes a driver instance for the given DMA engine and resets the engine.
  • -
  • Enable interrupts if chosen to use interrupt mode. The application is responsible for setting up the interrupt system, which includes providing and connecting interrupt handlers and call back functions, before enabling the interrupts.
  • -
  • Set the buffer address and length field in respective channels to start the DMA transfer
  • -
-

To use the SG mode DMA engine for transfers, the following setup are required:

-
    -
  • DMA Initialization using XAxiDma_CfgInitialize() function. This step initializes a driver instance for the given DMA engine and resets the engine.
  • -
  • BD Ring creation. A BD ring is needed per DMA channel and can be built by calling XAxiDma_BdRingCreate().
  • -
  • Enable interrupts if chose to use interrupt mode. The application is responsible for setting up the interrupt system, which includes providing and connecting interrupt handlers and call back functions, before enabling the interrupts.
  • -
  • Start a DMA transfer: Call XAxiDma_BdRingStart() to start a transfer for the first time or after a reset, and XAxiDma_BdRingToHw() if the channel is already started. Calling XAxiDma_BdRingToHw() when a DMA channel is not running will not put the BDs to the hardware, and the BDs will be processed later when the DMA channel is started through XAxiDma_BdRingStart().
  • -
-

How to start DMA transactions

-

The user application uses XAxiDma_BdRingToHw() to submit BDs to the hardware to start DMA transfers.

-

For both channels, if the DMA engine is currently stopped (using XAxiDma_Pause()), the newly added BDs will be accepted but not processed until the DMA engine is started, using XAxiDma_BdRingStart(), or resumed, using XAxiDma_Resume().

-

Software Post-Processing on completed DMA transactions

-

If the interrupt system has been set up and the interrupts are enabled, a DMA channels notifies the software about the completion of a transfer through interrupts. Otherwise, the user application can poll for completions of the BDs, using XAxiDma_BdRingFromHw() or XAxiDma_BdHwCompleted().

-
    -
  • Once BDs are finished by a channel, the application first needs to fetch them from the channel using XAxiDma_BdRingFromHw().
  • -
  • On the TX side, the application now could free the data buffers attached to those BDs as the data in the buffers has been transmitted.
  • -
  • On the RX side, the application now could use the received data in the buffers attached to those BDs.
  • -
  • For both channels, completed BDs need to be put back to the Free group using XAxiDma_BdRingFree(), so they can be used for future transactions.
  • -
  • On the RX side, it is the application's responsibility to have BDs ready to receive data at any time. Otherwise, the RX channel refuses to accept any data if it has no RX BDs.
  • -
-

Examples

-

We provide five examples to show how to use the driver API:

    -
  • One for SG interrupt mode (xaxidma_example_sg_intr.c), multiple BD/packets transfer
  • -
  • One for SG polling mode (xaxidma_example_sg_poll.c), single BD transfer.
  • -
  • One for SG polling mode (xaxidma_poll_multi_pkts.c), multiple BD/packets transfer
  • -
  • One for simple polling mode (xaxidma_example_simple_poll.c)
  • -
  • One for simple Interrupt mode (xaxidma_example_simple_intr.c)
  • -
-

Address Translation

-

All buffer addresses and BD addresses for the hardware are physical addresses. The user application is responsible to provide physical buffer address for the BD upon BD ring creation. The user application accesses BD through its virtual addess. The driver maintains the address translation between the physical and virtual address for BDs.

-

Cache Coherency

-

This driver expects all application buffers attached to BDs to be in cache coherent memory. If cache is used in the system, buffers for transmit MUST be flushed from the cache before passing the associated BD to this driver. Buffers for receive MUST be invalidated before accessing the data.

-

Alignment

-

For BDs:

-

Minimum alignment is defined by the constant XAXIDMA_BD_MINIMUM_ALIGNMENT. This is the smallest alignment allowed by both hardware and software for them to properly work.

-

If the descriptor ring is to be placed in cached memory, alignment also MUST be at least the processor's cache-line size. Otherwise, system instability occurs. For alignment larger than the cache line size, multiple cache line size alignment is required.

-

Aside from the initial creation of the descriptor ring (see XAxiDma_BdRingCreate()), there are no other run-time checks for proper alignment of BDs.

-

For application data buffers:

-

Application data buffers may reside on any alignment if DRE is built into the hardware. Otherwise, application data buffer must be word-aligned. The word is defined by XPAR_AXIDMA_0_M_AXIS_MM2S_TDATA_WIDTH for transmit and XPAR_AXIDMA_0_S_AXIS_S2MM_TDATA_WIDTH for receive.

-

For scatter gather transfers that have more than one BDs in the chain of BDs, Each BD transfer length must be multiple of word too. Otherwise, internal error happens in the hardware.

-

Error Handling

-

The DMA engine will halt on all error conditions. It requires the software to do a reset before it can start process new transfer requests.

-

Restart After Stopping

-

After the DMA engine has been stopped (through reset or reset after an error) the software keeps track of the current BD pointer when reset happens, and processing of BDs can be resumed through XAxiDma_BdRingStart().

-

Limitations

-

This driver does not have any mechanisms for mutual exclusion. It is up to the application to provide this protection.

-

Hardware Defaults & Exclusive Use

-

After the initialization or reset, the DMA engine is in the following default mode:

    -
  • All interrupts are disabled.
  • -
  • Interrupt coalescing counter is 1.
  • -
  • The DMA engine is not running (halted). Each DMA channel is started separately, using XAxiDma_StartBdRingHw() if no BDs are setup for transfer yet, or XAxiDma_BdRingStart() otherwise.
  • -
-

The driver has exclusive use of the registers and BDs. All accesses to the registers and BDs should go through the driver interface.

-

Debug Print

-

To see the debug print for the driver, please put "-DDEBUG" as the extra compiler flags in software platform settings. Also comment out the line in xdebug.h: "#undef DEBUG".

-

Changes From v1.00a

-

. We have changes return type for XAxiDma_BdSetBufAddr() from void to int . We added XAxiDma_LookupConfig() so that user does not need to look for the hardware settings anymore.

-
-MODIFICATION HISTORY:
Ver   Who  Date     Changes
------ ---- -------- -------------------------------------------------------
-1.00a jz   05/18/10 First release
-2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
-                    updated tcl file, added xaxidma_porting_guide.h
-3.00a jz   11/22/10 Support IP core parameters change
-4.00a rkv  02/22/11 Added support for simple DMA mode
-      	      New API added for simple DMA mode are

    -
  • XAxiDma_Busy
  • -
  • XAxiDma_SimpleTransfer - New Macros added for simple DMA mode are
      -
    • XAxiDma_HasSg
    • -
    • XAxiDma_IntrEnable
    • -
    • XAxiDma_IntrGetEnabled
    • -
    • XAxiDma_IntrDisable
    • -
    • XAxiDma_IntrGetIrq
    • -
    • XAxiDma_IntrAckIrq -5.00a srt 08/25/11 Added support for memory barrier and modified - Cache Macros to have a common API for Microblaze - and Zynq. -6.00a srt 01/24/12 Added support for Multi-Channel DMA mode.
    • -
    -
  • -
-
Changed APIs:
-      		* XAxiDma_GetRxRing(InstancePtr, RingIndex)
-      		* XAxiDma_Start(XAxiDma * InstancePtr, int RingIndex)
-      		* XAxiDma_Started(XAxiDma * InstancePtr, int RingIndex)
-      		* XAxiDma_Pause(XAxiDma * InstancePtr, int RingIndex)
-      		* XAxiDma_Resume(XAxiDma * InstancePtr, int RingIndex)
-      		* XAxiDma_SimpleTransfer(XAxiDma *InstancePtr,
-       					u32 BuffAddr, u32 Length,
-      					int Direction, int RingIndex)
-      		* XAxiDma_StartBdRingHw(XAxiDma_BdRing * RingPtr,
-      				int RingIndex)
-      		* XAxiDma_BdRingStart(XAxiDma_BdRing * RingPtr,
-      					 int RingIndex)
-      		* XAxiDma_BdRingToHw(XAxiDma_BdRing * RingPtr,
-       			int NumBd, XAxiDma_Bd * BdSetPtr, int RingIndex)
-      		* XAxiDma_BdRingDumpRegs(XAxiDma_BdRing * RingPtr,
-      					 int RingIndex)
-      		* XAxiDma_BdRingSnapShotCurrBd(XAxiDma_BdRing * RingPtr,
-      					 int RingIndex)
-      		* XAxiDma_BdSetLength(XAxiDma_Bd *BdPtr,
-      				u32 LenBytes, u32 LengthMask)
-      		* XAxiDma_BdGetActualLength(BdPtr, LengthMask)
-      		* XAxiDma_BdGetLength(BdPtr, LengthMask)

    -
  • New APIs - * XAxiDma_SelectKeyHole(XAxiDma *InstancePtr, - int Direction, int Select) - * XAxiDma_UpdateBdRingCDesc(XAxiDma_BdRing * RingPtr, - int RingIndex) -7.00a srt 06/18/12 All the APIs changed in v6_00_a are reverted back for - backward compatibility. -
  • -
  • Changed the logic of MCDMA BD fields Set APIs, to - clear the field first and then set it. -7.02a srt 01/23/13 Replaced *_TDATA_WIDTH parameters to *_DATA_WIDTH - (CR 691867) - Updated DDR base address for IPI designs (CR 703656). -8.0 adk 19/12/13 Updated as per the New Tcl API's - srt 01/29/14 Added support for Micro DMA Mode and cyclic mode of - operations.
  • -
-
New APIs:
-      		* XAxiDma_SelectCyclicMode(XAxiDma *InstancePtr,
-      					int Direction, int Select)
-			* XAxiDma_BdSetBufAddrMicroMode(XAxiDma_Bd*, u32)
-8.1   adk  20/01/15  Added support for peripheral test. Created the self
-      	       test example to include it on peripheral test's(CR#823144).
-8.1   adk  29/01/15  Added the sefltest api (XAxiDma_Selftest) to the driver source files
-		      (xaxidma_selftest.c) and called this from the selftest example
-9.0 	adk  27/07/15  Added support for 64-bit Addressing.
-9.0   adk  19/08/15  Fixed CR#873125 DMA SG Mode example tests are failing on
-      	       HW in 2015.3.
 
- - - diff --git a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/jquery.js b/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/jquery.js deleted file mode 100644 index 1f4d0b47c..000000000 --- a/thirdparty/libxil/orig/axidma_v9_0/doc/html/api/jquery.js +++ /dev/null @@ -1,68 +0,0 @@ -/*! - * jQuery JavaScript Library v1.7.1 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Mon Nov 21 21:11:03 2011 -0500 - */ -(function(bb,L){var av=bb.document,bu=bb.navigator,bl=bb.location;var b=(function(){var bF=function(b0,b1){return new bF.fn.init(b0,b1,bD)},bU=bb.jQuery,bH=bb.$,bD,bY=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,bM=/\S/,bI=/^\s+/,bE=/\s+$/,bA=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,bN=/^[\],:{}\s]*$/,bW=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,bP=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,bJ=/(?:^|:|,)(?:\s*\[)+/g,by=/(webkit)[ \/]([\w.]+)/,bR=/(opera)(?:.*version)?[ \/]([\w.]+)/,bQ=/(msie) ([\w.]+)/,bS=/(mozilla)(?:.*? rv:([\w.]+))?/,bB=/-([a-z]|[0-9])/ig,bZ=/^-ms-/,bT=function(b0,b1){return(b1+"").toUpperCase()},bX=bu.userAgent,bV,bC,e,bL=Object.prototype.toString,bG=Object.prototype.hasOwnProperty,bz=Array.prototype.push,bK=Array.prototype.slice,bO=String.prototype.trim,bv=Array.prototype.indexOf,bx={};bF.fn=bF.prototype={constructor:bF,init:function(b0,b4,b3){var b2,b5,b1,b6;if(!b0){return this}if(b0.nodeType){this.context=this[0]=b0;this.length=1;return this}if(b0==="body"&&!b4&&av.body){this.context=av;this[0]=av.body;this.selector=b0;this.length=1;return this}if(typeof b0==="string"){if(b0.charAt(0)==="<"&&b0.charAt(b0.length-1)===">"&&b0.length>=3){b2=[null,b0,null]}else{b2=bY.exec(b0)}if(b2&&(b2[1]||!b4)){if(b2[1]){b4=b4 instanceof bF?b4[0]:b4;b6=(b4?b4.ownerDocument||b4:av);b1=bA.exec(b0);if(b1){if(bF.isPlainObject(b4)){b0=[av.createElement(b1[1])];bF.fn.attr.call(b0,b4,true)}else{b0=[b6.createElement(b1[1])]}}else{b1=bF.buildFragment([b2[1]],[b6]);b0=(b1.cacheable?bF.clone(b1.fragment):b1.fragment).childNodes}return bF.merge(this,b0)}else{b5=av.getElementById(b2[2]);if(b5&&b5.parentNode){if(b5.id!==b2[2]){return b3.find(b0)}this.length=1;this[0]=b5}this.context=av;this.selector=b0;return this}}else{if(!b4||b4.jquery){return(b4||b3).find(b0)}else{return this.constructor(b4).find(b0)}}}else{if(bF.isFunction(b0)){return b3.ready(b0)}}if(b0.selector!==L){this.selector=b0.selector;this.context=b0.context}return bF.makeArray(b0,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return bK.call(this,0)},get:function(b0){return b0==null?this.toArray():(b0<0?this[this.length+b0]:this[b0])},pushStack:function(b1,b3,b0){var b2=this.constructor();if(bF.isArray(b1)){bz.apply(b2,b1)}else{bF.merge(b2,b1)}b2.prevObject=this;b2.context=this.context;if(b3==="find"){b2.selector=this.selector+(this.selector?" ":"")+b0}else{if(b3){b2.selector=this.selector+"."+b3+"("+b0+")"}}return b2},each:function(b1,b0){return bF.each(this,b1,b0)},ready:function(b0){bF.bindReady();bC.add(b0);return this},eq:function(b0){b0=+b0;return b0===-1?this.slice(b0):this.slice(b0,b0+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(bK.apply(this,arguments),"slice",bK.call(arguments).join(","))},map:function(b0){return this.pushStack(bF.map(this,function(b2,b1){return b0.call(b2,b1,b2)}))},end:function(){return this.prevObject||this.constructor(null)},push:bz,sort:[].sort,splice:[].splice};bF.fn.init.prototype=bF.fn;bF.extend=bF.fn.extend=function(){var b9,b2,b0,b1,b6,b7,b5=arguments[0]||{},b4=1,b3=arguments.length,b8=false;if(typeof b5==="boolean"){b8=b5;b5=arguments[1]||{};b4=2}if(typeof b5!=="object"&&!bF.isFunction(b5)){b5={}}if(b3===b4){b5=this;--b4}for(;b40){return}bC.fireWith(av,[bF]);if(bF.fn.trigger){bF(av).trigger("ready").off("ready")}}},bindReady:function(){if(bC){return}bC=bF.Callbacks("once memory");if(av.readyState==="complete"){return setTimeout(bF.ready,1)}if(av.addEventListener){av.addEventListener("DOMContentLoaded",e,false);bb.addEventListener("load",bF.ready,false)}else{if(av.attachEvent){av.attachEvent("onreadystatechange",e);bb.attachEvent("onload",bF.ready);var b0=false;try{b0=bb.frameElement==null}catch(b1){}if(av.documentElement.doScroll&&b0){bw()}}}},isFunction:function(b0){return bF.type(b0)==="function"},isArray:Array.isArray||function(b0){return bF.type(b0)==="array"},isWindow:function(b0){return b0&&typeof b0==="object"&&"setInterval" in b0},isNumeric:function(b0){return !isNaN(parseFloat(b0))&&isFinite(b0)},type:function(b0){return b0==null?String(b0):bx[bL.call(b0)]||"object"},isPlainObject:function(b2){if(!b2||bF.type(b2)!=="object"||b2.nodeType||bF.isWindow(b2)){return false}try{if(b2.constructor&&!bG.call(b2,"constructor")&&!bG.call(b2.constructor.prototype,"isPrototypeOf")){return false}}catch(b1){return false}var b0;for(b0 in b2){}return b0===L||bG.call(b2,b0)},isEmptyObject:function(b1){for(var b0 in b1){return false}return true},error:function(b0){throw new Error(b0)},parseJSON:function(b0){if(typeof b0!=="string"||!b0){return null}b0=bF.trim(b0);if(bb.JSON&&bb.JSON.parse){return bb.JSON.parse(b0)}if(bN.test(b0.replace(bW,"@").replace(bP,"]").replace(bJ,""))){return(new Function("return "+b0))()}bF.error("Invalid JSON: "+b0)},parseXML:function(b2){var b0,b1;try{if(bb.DOMParser){b1=new DOMParser();b0=b1.parseFromString(b2,"text/xml")}else{b0=new ActiveXObject("Microsoft.XMLDOM");b0.async="false";b0.loadXML(b2)}}catch(b3){b0=L}if(!b0||!b0.documentElement||b0.getElementsByTagName("parsererror").length){bF.error("Invalid XML: "+b2)}return b0},noop:function(){},globalEval:function(b0){if(b0&&bM.test(b0)){(bb.execScript||function(b1){bb["eval"].call(bb,b1)})(b0)}},camelCase:function(b0){return b0.replace(bZ,"ms-").replace(bB,bT)},nodeName:function(b1,b0){return b1.nodeName&&b1.nodeName.toUpperCase()===b0.toUpperCase()},each:function(b3,b6,b2){var b1,b4=0,b5=b3.length,b0=b5===L||bF.isFunction(b3);if(b2){if(b0){for(b1 in b3){if(b6.apply(b3[b1],b2)===false){break}}}else{for(;b40&&b0[0]&&b0[b1-1])||b1===0||bF.isArray(b0));if(b3){for(;b21?aJ.call(arguments,0):bG;if(!(--bw)){bC.resolveWith(bC,bx)}}}function bz(bF){return function(bG){bB[bF]=arguments.length>1?aJ.call(arguments,0):bG;bC.notifyWith(bE,bB)}}if(e>1){for(;bv
a";bI=bv.getElementsByTagName("*");bF=bv.getElementsByTagName("a")[0];if(!bI||!bI.length||!bF){return{}}bG=av.createElement("select");bx=bG.appendChild(av.createElement("option"));bE=bv.getElementsByTagName("input")[0];bJ={leadingWhitespace:(bv.firstChild.nodeType===3),tbody:!bv.getElementsByTagName("tbody").length,htmlSerialize:!!bv.getElementsByTagName("link").length,style:/top/.test(bF.getAttribute("style")),hrefNormalized:(bF.getAttribute("href")==="/a"),opacity:/^0.55/.test(bF.style.opacity),cssFloat:!!bF.style.cssFloat,checkOn:(bE.value==="on"),optSelected:bx.selected,getSetAttribute:bv.className!=="t",enctype:!!av.createElement("form").enctype,html5Clone:av.createElement("nav").cloneNode(true).outerHTML!=="<:nav>",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true};bE.checked=true;bJ.noCloneChecked=bE.cloneNode(true).checked;bG.disabled=true;bJ.optDisabled=!bx.disabled;try{delete bv.test}catch(bC){bJ.deleteExpando=false}if(!bv.addEventListener&&bv.attachEvent&&bv.fireEvent){bv.attachEvent("onclick",function(){bJ.noCloneEvent=false});bv.cloneNode(true).fireEvent("onclick")}bE=av.createElement("input");bE.value="t";bE.setAttribute("type","radio");bJ.radioValue=bE.value==="t";bE.setAttribute("checked","checked");bv.appendChild(bE);bD=av.createDocumentFragment();bD.appendChild(bv.lastChild);bJ.checkClone=bD.cloneNode(true).cloneNode(true).lastChild.checked;bJ.appendChecked=bE.checked;bD.removeChild(bE);bD.appendChild(bv);bv.innerHTML="";if(bb.getComputedStyle){bA=av.createElement("div");bA.style.width="0";bA.style.marginRight="0";bv.style.width="2px";bv.appendChild(bA);bJ.reliableMarginRight=(parseInt((bb.getComputedStyle(bA,null)||{marginRight:0}).marginRight,10)||0)===0}if(bv.attachEvent){for(by in {submit:1,change:1,focusin:1}){bB="on"+by;bw=(bB in bv);if(!bw){bv.setAttribute(bB,"return;");bw=(typeof bv[bB]==="function")}bJ[by+"Bubbles"]=bw}}bD.removeChild(bv);bD=bG=bx=bA=bv=bE=null;b(function(){var bM,bU,bV,bT,bN,bO,bL,bS,bR,e,bP,bQ=av.getElementsByTagName("body")[0];if(!bQ){return}bL=1;bS="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";bR="visibility:hidden;border:0;";e="style='"+bS+"border:5px solid #000;padding:0;'";bP="
";bM=av.createElement("div");bM.style.cssText=bR+"width:0;height:0;position:static;top:0;margin-top:"+bL+"px";bQ.insertBefore(bM,bQ.firstChild);bv=av.createElement("div");bM.appendChild(bv);bv.innerHTML="
t
";bz=bv.getElementsByTagName("td");bw=(bz[0].offsetHeight===0);bz[0].style.display="";bz[1].style.display="none";bJ.reliableHiddenOffsets=bw&&(bz[0].offsetHeight===0);bv.innerHTML="";bv.style.width=bv.style.paddingLeft="1px";b.boxModel=bJ.boxModel=bv.offsetWidth===2;if(typeof bv.style.zoom!=="undefined"){bv.style.display="inline";bv.style.zoom=1;bJ.inlineBlockNeedsLayout=(bv.offsetWidth===2);bv.style.display="";bv.innerHTML="
";bJ.shrinkWrapBlocks=(bv.offsetWidth!==2)}bv.style.cssText=bS+bR;bv.innerHTML=bP;bU=bv.firstChild;bV=bU.firstChild;bN=bU.nextSibling.firstChild.firstChild;bO={doesNotAddBorder:(bV.offsetTop!==5),doesAddBorderForTableAndCells:(bN.offsetTop===5)};bV.style.position="fixed";bV.style.top="20px";bO.fixedPosition=(bV.offsetTop===20||bV.offsetTop===15);bV.style.position=bV.style.top="";bU.style.overflow="hidden";bU.style.position="relative";bO.subtractsBorderForOverflowNotVisible=(bV.offsetTop===-5);bO.doesNotIncludeMarginInBodyOffset=(bQ.offsetTop!==bL);bQ.removeChild(bM);bv=bM=null;b.extend(bJ,bO)});return bJ})();var aS=/^(?:\{.*\}|\[.*\])$/,aA=/([A-Z])/g;b.extend({cache:{},uuid:0,expando:"jQuery"+(b.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(e){e=e.nodeType?b.cache[e[b.expando]]:e[b.expando];return !!e&&!S(e)},data:function(bx,bv,bz,by){if(!b.acceptData(bx)){return}var bG,bA,bD,bE=b.expando,bC=typeof bv==="string",bF=bx.nodeType,e=bF?b.cache:bx,bw=bF?bx[bE]:bx[bE]&&bE,bB=bv==="events";if((!bw||!e[bw]||(!bB&&!by&&!e[bw].data))&&bC&&bz===L){return}if(!bw){if(bF){bx[bE]=bw=++b.uuid}else{bw=bE}}if(!e[bw]){e[bw]={};if(!bF){e[bw].toJSON=b.noop}}if(typeof bv==="object"||typeof bv==="function"){if(by){e[bw]=b.extend(e[bw],bv)}else{e[bw].data=b.extend(e[bw].data,bv)}}bG=bA=e[bw];if(!by){if(!bA.data){bA.data={}}bA=bA.data}if(bz!==L){bA[b.camelCase(bv)]=bz}if(bB&&!bA[bv]){return bG.events}if(bC){bD=bA[bv];if(bD==null){bD=bA[b.camelCase(bv)]}}else{bD=bA}return bD},removeData:function(bx,bv,by){if(!b.acceptData(bx)){return}var bB,bA,bz,bC=b.expando,bD=bx.nodeType,e=bD?b.cache:bx,bw=bD?bx[bC]:bC;if(!e[bw]){return}if(bv){bB=by?e[bw]:e[bw].data;if(bB){if(!b.isArray(bv)){if(bv in bB){bv=[bv]}else{bv=b.camelCase(bv);if(bv in bB){bv=[bv]}else{bv=bv.split(" ")}}}for(bA=0,bz=bv.length;bA-1){return true}}return false},val:function(bx){var e,bv,by,bw=this[0];if(!arguments.length){if(bw){e=b.valHooks[bw.nodeName.toLowerCase()]||b.valHooks[bw.type];if(e&&"get" in e&&(bv=e.get(bw,"value"))!==L){return bv}bv=bw.value;return typeof bv==="string"?bv.replace(aU,""):bv==null?"":bv}return}by=b.isFunction(bx);return this.each(function(bA){var bz=b(this),bB;if(this.nodeType!==1){return}if(by){bB=bx.call(this,bA,bz.val())}else{bB=bx}if(bB==null){bB=""}else{if(typeof bB==="number"){bB+=""}else{if(b.isArray(bB)){bB=b.map(bB,function(bC){return bC==null?"":bC+""})}}}e=b.valHooks[this.nodeName.toLowerCase()]||b.valHooks[this.type];if(!e||!("set" in e)||e.set(this,bB,"value")===L){this.value=bB}})}});b.extend({valHooks:{option:{get:function(e){var bv=e.attributes.value;return !bv||bv.specified?e.value:e.text}},select:{get:function(e){var bA,bv,bz,bx,by=e.selectedIndex,bB=[],bC=e.options,bw=e.type==="select-one";if(by<0){return null}bv=bw?by:0;bz=bw?by+1:bC.length;for(;bv=0});if(!e.length){bv.selectedIndex=-1}return e}}},attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(bA,bx,bB,bz){var bw,e,by,bv=bA.nodeType;if(!bA||bv===3||bv===8||bv===2){return}if(bz&&bx in b.attrFn){return b(bA)[bx](bB)}if(typeof bA.getAttribute==="undefined"){return b.prop(bA,bx,bB)}by=bv!==1||!b.isXMLDoc(bA);if(by){bx=bx.toLowerCase();e=b.attrHooks[bx]||(ao.test(bx)?aY:be)}if(bB!==L){if(bB===null){b.removeAttr(bA,bx);return}else{if(e&&"set" in e&&by&&(bw=e.set(bA,bB,bx))!==L){return bw}else{bA.setAttribute(bx,""+bB);return bB}}}else{if(e&&"get" in e&&by&&(bw=e.get(bA,bx))!==null){return bw}else{bw=bA.getAttribute(bx);return bw===null?L:bw}}},removeAttr:function(bx,bz){var by,bA,bv,e,bw=0;if(bz&&bx.nodeType===1){bA=bz.toLowerCase().split(af);e=bA.length;for(;bw=0)}}})});var bd=/^(?:textarea|input|select)$/i,n=/^([^\.]*)?(?:\.(.+))?$/,J=/\bhover(\.\S+)?\b/,aO=/^key/,bf=/^(?:mouse|contextmenu)|click/,T=/^(?:focusinfocus|focusoutblur)$/,U=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,Y=function(e){var bv=U.exec(e);if(bv){bv[1]=(bv[1]||"").toLowerCase();bv[3]=bv[3]&&new RegExp("(?:^|\\s)"+bv[3]+"(?:\\s|$)")}return bv},j=function(bw,e){var bv=bw.attributes||{};return((!e[1]||bw.nodeName.toLowerCase()===e[1])&&(!e[2]||(bv.id||{}).value===e[2])&&(!e[3]||e[3].test((bv["class"]||{}).value)))},bt=function(e){return b.event.special.hover?e:e.replace(J,"mouseenter$1 mouseleave$1")};b.event={add:function(bx,bC,bJ,bA,by){var bD,bB,bK,bI,bH,bF,e,bG,bv,bz,bw,bE;if(bx.nodeType===3||bx.nodeType===8||!bC||!bJ||!(bD=b._data(bx))){return}if(bJ.handler){bv=bJ;bJ=bv.handler}if(!bJ.guid){bJ.guid=b.guid++}bK=bD.events;if(!bK){bD.events=bK={}}bB=bD.handle;if(!bB){bD.handle=bB=function(bL){return typeof b!=="undefined"&&(!bL||b.event.triggered!==bL.type)?b.event.dispatch.apply(bB.elem,arguments):L};bB.elem=bx}bC=b.trim(bt(bC)).split(" ");for(bI=0;bI=0){bG=bG.slice(0,-1);bw=true}if(bG.indexOf(".")>=0){bx=bG.split(".");bG=bx.shift();bx.sort()}if((!bA||b.event.customEvent[bG])&&!b.event.global[bG]){return}bv=typeof bv==="object"?bv[b.expando]?bv:new b.Event(bG,bv):new b.Event(bG);bv.type=bG;bv.isTrigger=true;bv.exclusive=bw;bv.namespace=bx.join(".");bv.namespace_re=bv.namespace?new RegExp("(^|\\.)"+bx.join("\\.(?:.*\\.)?")+"(\\.|$)"):null;by=bG.indexOf(":")<0?"on"+bG:"";if(!bA){e=b.cache;for(bC in e){if(e[bC].events&&e[bC].events[bG]){b.event.trigger(bv,bD,e[bC].handle.elem,true)}}return}bv.result=L;if(!bv.target){bv.target=bA}bD=bD!=null?b.makeArray(bD):[];bD.unshift(bv);bF=b.event.special[bG]||{};if(bF.trigger&&bF.trigger.apply(bA,bD)===false){return}bB=[[bA,bF.bindType||bG]];if(!bJ&&!bF.noBubble&&!b.isWindow(bA)){bI=bF.delegateType||bG;bH=T.test(bI+bG)?bA:bA.parentNode;bz=null;for(;bH;bH=bH.parentNode){bB.push([bH,bI]);bz=bH}if(bz&&bz===bA.ownerDocument){bB.push([bz.defaultView||bz.parentWindow||bb,bI])}}for(bC=0;bCbA){bH.push({elem:this,matches:bz.slice(bA)})}for(bC=0;bC0?this.on(e,null,bx,bw):this.trigger(e)};if(b.attrFn){b.attrFn[e]=true}if(aO.test(e)){b.event.fixHooks[e]=b.event.keyHooks}if(bf.test(e)){b.event.fixHooks[e]=b.event.mouseHooks}}); -/*! - * Sizzle CSS Selector Engine - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){var bH=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,bC="sizcache"+(Math.random()+"").replace(".",""),bI=0,bL=Object.prototype.toString,bB=false,bA=true,bK=/\\/g,bO=/\r\n/g,bQ=/\W/;[0,0].sort(function(){bA=false;return 0});var by=function(bV,e,bY,bZ){bY=bY||[];e=e||av;var b1=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!bV||typeof bV!=="string"){return bY}var bS,b3,b6,bR,b2,b5,b4,bX,bU=true,bT=by.isXML(e),bW=[],b0=bV;do{bH.exec("");bS=bH.exec(b0);if(bS){b0=bS[3];bW.push(bS[1]);if(bS[2]){bR=bS[3];break}}}while(bS);if(bW.length>1&&bD.exec(bV)){if(bW.length===2&&bE.relative[bW[0]]){b3=bM(bW[0]+bW[1],e,bZ)}else{b3=bE.relative[bW[0]]?[e]:by(bW.shift(),e);while(bW.length){bV=bW.shift();if(bE.relative[bV]){bV+=bW.shift()}b3=bM(bV,b3,bZ)}}}else{if(!bZ&&bW.length>1&&e.nodeType===9&&!bT&&bE.match.ID.test(bW[0])&&!bE.match.ID.test(bW[bW.length-1])){b2=by.find(bW.shift(),e,bT);e=b2.expr?by.filter(b2.expr,b2.set)[0]:b2.set[0]}if(e){b2=bZ?{expr:bW.pop(),set:bF(bZ)}:by.find(bW.pop(),bW.length===1&&(bW[0]==="~"||bW[0]==="+")&&e.parentNode?e.parentNode:e,bT);b3=b2.expr?by.filter(b2.expr,b2.set):b2.set;if(bW.length>0){b6=bF(b3)}else{bU=false}while(bW.length){b5=bW.pop();b4=b5;if(!bE.relative[b5]){b5=""}else{b4=bW.pop()}if(b4==null){b4=e}bE.relative[b5](b6,b4,bT)}}else{b6=bW=[]}}if(!b6){b6=b3}if(!b6){by.error(b5||bV)}if(bL.call(b6)==="[object Array]"){if(!bU){bY.push.apply(bY,b6)}else{if(e&&e.nodeType===1){for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&(b6[bX]===true||b6[bX].nodeType===1&&by.contains(e,b6[bX]))){bY.push(b3[bX])}}}else{for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&b6[bX].nodeType===1){bY.push(b3[bX])}}}}}else{bF(b6,bY)}if(bR){by(bR,b1,bY,bZ);by.uniqueSort(bY)}return bY};by.uniqueSort=function(bR){if(bJ){bB=bA;bR.sort(bJ);if(bB){for(var e=1;e0};by.find=function(bX,e,bY){var bW,bS,bU,bT,bV,bR;if(!bX){return[]}for(bS=0,bU=bE.order.length;bS":function(bW,bR){var bV,bU=typeof bR==="string",bS=0,e=bW.length;if(bU&&!bQ.test(bR)){bR=bR.toLowerCase();for(;bS=0)){if(!bS){e.push(bV)}}else{if(bS){bR[bU]=false}}}}return false},ID:function(e){return e[1].replace(bK,"")},TAG:function(bR,e){return bR[1].replace(bK,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){by.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var bR=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(bR[1]+(bR[2]||1))-0;e[3]=bR[3]-0}else{if(e[2]){by.error(e[0])}}e[0]=bI++;return e},ATTR:function(bU,bR,bS,e,bV,bW){var bT=bU[1]=bU[1].replace(bK,"");if(!bW&&bE.attrMap[bT]){bU[1]=bE.attrMap[bT]}bU[4]=(bU[4]||bU[5]||"").replace(bK,"");if(bU[2]==="~="){bU[4]=" "+bU[4]+" "}return bU},PSEUDO:function(bU,bR,bS,e,bV){if(bU[1]==="not"){if((bH.exec(bU[3])||"").length>1||/^\w/.test(bU[3])){bU[3]=by(bU[3],null,null,bR)}else{var bT=by.filter(bU[3],bR,bS,true^bV);if(!bS){e.push.apply(e,bT)}return false}}else{if(bE.match.POS.test(bU[0])||bE.match.CHILD.test(bU[0])){return true}}return bU},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(bS,bR,e){return !!by(e[3],bS).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(bS){var e=bS.getAttribute("type"),bR=bS.type;return bS.nodeName.toLowerCase()==="input"&&"text"===bR&&(e===bR||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===bR.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===bR.type},button:function(bR){var e=bR.nodeName.toLowerCase();return e==="input"&&"button"===bR.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(bR,e){return e===0},last:function(bS,bR,e,bT){return bR===bT.length-1},even:function(bR,e){return e%2===0},odd:function(bR,e){return e%2===1},lt:function(bS,bR,e){return bRe[3]-0},nth:function(bS,bR,e){return e[3]-0===bR},eq:function(bS,bR,e){return e[3]-0===bR}},filter:{PSEUDO:function(bS,bX,bW,bY){var e=bX[1],bR=bE.filters[e];if(bR){return bR(bS,bW,bX,bY)}else{if(e==="contains"){return(bS.textContent||bS.innerText||bw([bS])||"").indexOf(bX[3])>=0}else{if(e==="not"){var bT=bX[3];for(var bV=0,bU=bT.length;bV=0)}}},ID:function(bR,e){return bR.nodeType===1&&bR.getAttribute("id")===e},TAG:function(bR,e){return(e==="*"&&bR.nodeType===1)||!!bR.nodeName&&bR.nodeName.toLowerCase()===e},CLASS:function(bR,e){return(" "+(bR.className||bR.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(bV,bT){var bS=bT[1],e=by.attr?by.attr(bV,bS):bE.attrHandle[bS]?bE.attrHandle[bS](bV):bV[bS]!=null?bV[bS]:bV.getAttribute(bS),bW=e+"",bU=bT[2],bR=bT[4];return e==null?bU==="!=":!bU&&by.attr?e!=null:bU==="="?bW===bR:bU==="*="?bW.indexOf(bR)>=0:bU==="~="?(" "+bW+" ").indexOf(bR)>=0:!bR?bW&&e!==false:bU==="!="?bW!==bR:bU==="^="?bW.indexOf(bR)===0:bU==="$="?bW.substr(bW.length-bR.length)===bR:bU==="|="?bW===bR||bW.substr(0,bR.length+1)===bR+"-":false},POS:function(bU,bR,bS,bV){var e=bR[2],bT=bE.setFilters[e];if(bT){return bT(bU,bS,bR,bV)}}}};var bD=bE.match.POS,bx=function(bR,e){return"\\"+(e-0+1)};for(var bz in bE.match){bE.match[bz]=new RegExp(bE.match[bz].source+(/(?![^\[]*\])(?![^\(]*\))/.source));bE.leftMatch[bz]=new RegExp(/(^(?:.|\r|\n)*?)/.source+bE.match[bz].source.replace(/\\(\d+)/g,bx))}var bF=function(bR,e){bR=Array.prototype.slice.call(bR,0);if(e){e.push.apply(e,bR);return e}return bR};try{Array.prototype.slice.call(av.documentElement.childNodes,0)[0].nodeType}catch(bP){bF=function(bU,bT){var bS=0,bR=bT||[];if(bL.call(bU)==="[object Array]"){Array.prototype.push.apply(bR,bU)}else{if(typeof bU.length==="number"){for(var e=bU.length;bS";e.insertBefore(bR,e.firstChild);if(av.getElementById(bS)){bE.find.ID=function(bU,bV,bW){if(typeof bV.getElementById!=="undefined"&&!bW){var bT=bV.getElementById(bU[1]);return bT?bT.id===bU[1]||typeof bT.getAttributeNode!=="undefined"&&bT.getAttributeNode("id").nodeValue===bU[1]?[bT]:L:[]}};bE.filter.ID=function(bV,bT){var bU=typeof bV.getAttributeNode!=="undefined"&&bV.getAttributeNode("id");return bV.nodeType===1&&bU&&bU.nodeValue===bT}}e.removeChild(bR);e=bR=null})();(function(){var e=av.createElement("div");e.appendChild(av.createComment(""));if(e.getElementsByTagName("*").length>0){bE.find.TAG=function(bR,bV){var bU=bV.getElementsByTagName(bR[1]);if(bR[1]==="*"){var bT=[];for(var bS=0;bU[bS];bS++){if(bU[bS].nodeType===1){bT.push(bU[bS])}}bU=bT}return bU}}e.innerHTML="";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){bE.attrHandle.href=function(bR){return bR.getAttribute("href",2)}}e=null})();if(av.querySelectorAll){(function(){var e=by,bT=av.createElement("div"),bS="__sizzle__";bT.innerHTML="

";if(bT.querySelectorAll&&bT.querySelectorAll(".TEST").length===0){return}by=function(b4,bV,bZ,b3){bV=bV||av;if(!b3&&!by.isXML(bV)){var b2=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b4);if(b2&&(bV.nodeType===1||bV.nodeType===9)){if(b2[1]){return bF(bV.getElementsByTagName(b4),bZ)}else{if(b2[2]&&bE.find.CLASS&&bV.getElementsByClassName){return bF(bV.getElementsByClassName(b2[2]),bZ)}}}if(bV.nodeType===9){if(b4==="body"&&bV.body){return bF([bV.body],bZ)}else{if(b2&&b2[3]){var bY=bV.getElementById(b2[3]);if(bY&&bY.parentNode){if(bY.id===b2[3]){return bF([bY],bZ)}}else{return bF([],bZ)}}}try{return bF(bV.querySelectorAll(b4),bZ)}catch(b0){}}else{if(bV.nodeType===1&&bV.nodeName.toLowerCase()!=="object"){var bW=bV,bX=bV.getAttribute("id"),bU=bX||bS,b6=bV.parentNode,b5=/^\s*[+~]/.test(b4);if(!bX){bV.setAttribute("id",bU)}else{bU=bU.replace(/'/g,"\\$&")}if(b5&&b6){bV=bV.parentNode}try{if(!b5||b6){return bF(bV.querySelectorAll("[id='"+bU+"'] "+b4),bZ)}}catch(b1){}finally{if(!bX){bW.removeAttribute("id")}}}}}return e(b4,bV,bZ,b3)};for(var bR in e){by[bR]=e[bR]}bT=null})()}(function(){var e=av.documentElement,bS=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(bS){var bU=!bS.call(av.createElement("div"),"div"),bR=false;try{bS.call(av.documentElement,"[test!='']:sizzle")}catch(bT){bR=true}by.matchesSelector=function(bW,bY){bY=bY.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!by.isXML(bW)){try{if(bR||!bE.match.PSEUDO.test(bY)&&!/!=/.test(bY)){var bV=bS.call(bW,bY);if(bV||!bU||bW.document&&bW.document.nodeType!==11){return bV}}}catch(bX){}}return by(bY,null,null,[bW]).length>0}}})();(function(){var e=av.createElement("div");e.innerHTML="
";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}bE.order.splice(1,0,"CLASS");bE.find.CLASS=function(bR,bS,bT){if(typeof bS.getElementsByClassName!=="undefined"&&!bT){return bS.getElementsByClassName(bR[1])}};e=null})();function bv(bR,bW,bV,bZ,bX,bY){for(var bT=0,bS=bZ.length;bT0){bU=e;break}}}e=e[bR]}bZ[bT]=bU}}}if(av.documentElement.contains){by.contains=function(bR,e){return bR!==e&&(bR.contains?bR.contains(e):true)}}else{if(av.documentElement.compareDocumentPosition){by.contains=function(bR,e){return !!(bR.compareDocumentPosition(e)&16)}}else{by.contains=function(){return false}}}by.isXML=function(e){var bR=(e?e.ownerDocument||e:0).documentElement;return bR?bR.nodeName!=="HTML":false};var bM=function(bS,e,bW){var bV,bX=[],bU="",bY=e.nodeType?[e]:e;while((bV=bE.match.PSEUDO.exec(bS))){bU+=bV[0];bS=bS.replace(bE.match.PSEUDO,"")}bS=bE.relative[bS]?bS+"*":bS;for(var bT=0,bR=bY.length;bT0){for(bB=bA;bB=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(by,bx){var bv=[],bw,e,bz=this[0];if(b.isArray(by)){var bB=1;while(bz&&bz.ownerDocument&&bz!==bx){for(bw=0;bw-1:b.find.matchesSelector(bz,by)){bv.push(bz);break}else{bz=bz.parentNode;if(!bz||!bz.ownerDocument||bz===bx||bz.nodeType===11){break}}}}bv=bv.length>1?b.unique(bv):bv;return this.pushStack(bv,"closest",by)},index:function(e){if(!e){return(this[0]&&this[0].parentNode)?this.prevAll().length:-1}if(typeof e==="string"){return b.inArray(this[0],b(e))}return b.inArray(e.jquery?e[0]:e,this)},add:function(e,bv){var bx=typeof e==="string"?b(e,bv):b.makeArray(e&&e.nodeType?[e]:e),bw=b.merge(this.get(),bx);return this.pushStack(C(bx[0])||C(bw[0])?bw:b.unique(bw))},andSelf:function(){return this.add(this.prevObject)}});function C(e){return !e||!e.parentNode||e.parentNode.nodeType===11}b.each({parent:function(bv){var e=bv.parentNode;return e&&e.nodeType!==11?e:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(bv,e,bw){return b.dir(bv,"parentNode",bw)},next:function(e){return b.nth(e,2,"nextSibling")},prev:function(e){return b.nth(e,2,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(bv,e,bw){return b.dir(bv,"nextSibling",bw)},prevUntil:function(bv,e,bw){return b.dir(bv,"previousSibling",bw)},siblings:function(e){return b.sibling(e.parentNode.firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.makeArray(e.childNodes)}},function(e,bv){b.fn[e]=function(by,bw){var bx=b.map(this,bv,by);if(!ab.test(e)){bw=by}if(bw&&typeof bw==="string"){bx=b.filter(bw,bx)}bx=this.length>1&&!ay[e]?b.unique(bx):bx;if((this.length>1||a9.test(bw))&&aq.test(e)){bx=bx.reverse()}return this.pushStack(bx,e,P.call(arguments).join(","))}});b.extend({filter:function(bw,e,bv){if(bv){bw=":not("+bw+")"}return e.length===1?b.find.matchesSelector(e[0],bw)?[e[0]]:[]:b.find.matches(bw,e)},dir:function(bw,bv,by){var e=[],bx=bw[bv];while(bx&&bx.nodeType!==9&&(by===L||bx.nodeType!==1||!b(bx).is(by))){if(bx.nodeType===1){e.push(bx)}bx=bx[bv]}return e},nth:function(by,e,bw,bx){e=e||1;var bv=0;for(;by;by=by[bw]){if(by.nodeType===1&&++bv===e){break}}return by},sibling:function(bw,bv){var e=[];for(;bw;bw=bw.nextSibling){if(bw.nodeType===1&&bw!==bv){e.push(bw)}}return e}});function aG(bx,bw,e){bw=bw||0;if(b.isFunction(bw)){return b.grep(bx,function(bz,by){var bA=!!bw.call(bz,by,bz);return bA===e})}else{if(bw.nodeType){return b.grep(bx,function(bz,by){return(bz===bw)===e})}else{if(typeof bw==="string"){var bv=b.grep(bx,function(by){return by.nodeType===1});if(bp.test(bw)){return b.filter(bw,bv,!e)}else{bw=b.filter(bw,bv)}}}}return b.grep(bx,function(bz,by){return(b.inArray(bz,bw)>=0)===e})}function a(e){var bw=aR.split("|"),bv=e.createDocumentFragment();if(bv.createElement){while(bw.length){bv.createElement(bw.pop())}}return bv}var aR="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ag=/ jQuery\d+="(?:\d+|null)"/g,ar=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,d=/<([\w:]+)/,w=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},ac=a(av);ax.optgroup=ax.option;ax.tbody=ax.tfoot=ax.colgroup=ax.caption=ax.thead;ax.th=ax.td;if(!b.support.htmlSerialize){ax._default=[1,"div
","
"]}b.fn.extend({text:function(e){if(b.isFunction(e)){return this.each(function(bw){var bv=b(this);bv.text(e.call(this,bw,bv.text()))})}if(typeof e!=="object"&&e!==L){return this.empty().append((this[0]&&this[0].ownerDocument||av).createTextNode(e))}return b.text(this)},wrapAll:function(e){if(b.isFunction(e)){return this.each(function(bw){b(this).wrapAll(e.call(this,bw))})}if(this[0]){var bv=b(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){bv.insertBefore(this[0])}bv.map(function(){var bw=this;while(bw.firstChild&&bw.firstChild.nodeType===1){bw=bw.firstChild}return bw}).append(this)}return this},wrapInner:function(e){if(b.isFunction(e)){return this.each(function(bv){b(this).wrapInner(e.call(this,bv))})}return this.each(function(){var bv=b(this),bw=bv.contents();if(bw.length){bw.wrapAll(e)}else{bv.append(e)}})},wrap:function(e){var bv=b.isFunction(e);return this.each(function(bw){b(this).wrapAll(bv?e.call(this,bw):e)})},unwrap:function(){return this.parent().each(function(){if(!b.nodeName(this,"body")){b(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.appendChild(e)}})},prepend:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.insertBefore(e,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this)})}else{if(arguments.length){var e=b.clean(arguments);e.push.apply(e,this.toArray());return this.pushStack(e,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this.nextSibling)})}else{if(arguments.length){var e=this.pushStack(this,"after",arguments);e.push.apply(e,b.clean(arguments));return e}}},remove:function(e,bx){for(var bv=0,bw;(bw=this[bv])!=null;bv++){if(!e||b.filter(e,[bw]).length){if(!bx&&bw.nodeType===1){b.cleanData(bw.getElementsByTagName("*"));b.cleanData([bw])}if(bw.parentNode){bw.parentNode.removeChild(bw)}}}return this},empty:function(){for(var e=0,bv;(bv=this[e])!=null;e++){if(bv.nodeType===1){b.cleanData(bv.getElementsByTagName("*"))}while(bv.firstChild){bv.removeChild(bv.firstChild)}}return this},clone:function(bv,e){bv=bv==null?false:bv;e=e==null?bv:e;return this.map(function(){return b.clone(this,bv,e)})},html:function(bx){if(bx===L){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(ag,""):null}else{if(typeof bx==="string"&&!ae.test(bx)&&(b.support.leadingWhitespace||!ar.test(bx))&&!ax[(d.exec(bx)||["",""])[1].toLowerCase()]){bx=bx.replace(R,"<$1>");try{for(var bw=0,bv=this.length;bw1&&bw0?this.clone(true):this).get();b(bC[bA])[bv](by);bz=bz.concat(by)}return this.pushStack(bz,e,bC.selector)}}});function bg(e){if(typeof e.getElementsByTagName!=="undefined"){return e.getElementsByTagName("*")}else{if(typeof e.querySelectorAll!=="undefined"){return e.querySelectorAll("*")}else{return[]}}}function az(e){if(e.type==="checkbox"||e.type==="radio"){e.defaultChecked=e.checked}}function E(e){var bv=(e.nodeName||"").toLowerCase();if(bv==="input"){az(e)}else{if(bv!=="script"&&typeof e.getElementsByTagName!=="undefined"){b.grep(e.getElementsByTagName("input"),az)}}}function al(e){var bv=av.createElement("div");ac.appendChild(bv);bv.innerHTML=e.outerHTML;return bv.firstChild}b.extend({clone:function(by,bA,bw){var e,bv,bx,bz=b.support.html5Clone||!ah.test("<"+by.nodeName)?by.cloneNode(true):al(by);if((!b.support.noCloneEvent||!b.support.noCloneChecked)&&(by.nodeType===1||by.nodeType===11)&&!b.isXMLDoc(by)){ai(by,bz);e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){if(bv[bx]){ai(e[bx],bv[bx])}}}if(bA){t(by,bz);if(bw){e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){t(e[bx],bv[bx])}}}e=bv=null;return bz},clean:function(bw,by,bH,bA){var bF;by=by||av;if(typeof by.createElement==="undefined"){by=by.ownerDocument||by[0]&&by[0].ownerDocument||av}var bI=[],bB;for(var bE=0,bz;(bz=bw[bE])!=null;bE++){if(typeof bz==="number"){bz+=""}if(!bz){continue}if(typeof bz==="string"){if(!W.test(bz)){bz=by.createTextNode(bz)}else{bz=bz.replace(R,"<$1>");var bK=(d.exec(bz)||["",""])[1].toLowerCase(),bx=ax[bK]||ax._default,bD=bx[0],bv=by.createElement("div");if(by===av){ac.appendChild(bv)}else{a(by).appendChild(bv)}bv.innerHTML=bx[1]+bz+bx[2];while(bD--){bv=bv.lastChild}if(!b.support.tbody){var e=w.test(bz),bC=bK==="table"&&!e?bv.firstChild&&bv.firstChild.childNodes:bx[1]===""&&!e?bv.childNodes:[];for(bB=bC.length-1;bB>=0;--bB){if(b.nodeName(bC[bB],"tbody")&&!bC[bB].childNodes.length){bC[bB].parentNode.removeChild(bC[bB])}}}if(!b.support.leadingWhitespace&&ar.test(bz)){bv.insertBefore(by.createTextNode(ar.exec(bz)[0]),bv.firstChild)}bz=bv.childNodes}}var bG;if(!b.support.appendChecked){if(bz[0]&&typeof(bG=bz.length)==="number"){for(bB=0;bB=0){return bx+"px"}}else{return bx}}}});if(!b.support.opacity){b.cssHooks.opacity={get:function(bv,e){return au.test((e&&bv.currentStyle?bv.currentStyle.filter:bv.style.filter)||"")?(parseFloat(RegExp.$1)/100)+"":e?"1":""},set:function(by,bz){var bx=by.style,bv=by.currentStyle,e=b.isNumeric(bz)?"alpha(opacity="+bz*100+")":"",bw=bv&&bv.filter||bx.filter||"";bx.zoom=1;if(bz>=1&&b.trim(bw.replace(ak,""))===""){bx.removeAttribute("filter");if(bv&&!bv.filter){return}}bx.filter=ak.test(bw)?bw.replace(ak,e):bw+" "+e}}}b(function(){if(!b.support.reliableMarginRight){b.cssHooks.marginRight={get:function(bw,bv){var e;b.swap(bw,{display:"inline-block"},function(){if(bv){e=Z(bw,"margin-right","marginRight")}else{e=bw.style.marginRight}});return e}}}});if(av.defaultView&&av.defaultView.getComputedStyle){aI=function(by,bw){var bv,bx,e;bw=bw.replace(z,"-$1").toLowerCase();if((bx=by.ownerDocument.defaultView)&&(e=bx.getComputedStyle(by,null))){bv=e.getPropertyValue(bw);if(bv===""&&!b.contains(by.ownerDocument.documentElement,by)){bv=b.style(by,bw)}}return bv}}if(av.documentElement.currentStyle){aX=function(bz,bw){var bA,e,by,bv=bz.currentStyle&&bz.currentStyle[bw],bx=bz.style;if(bv===null&&bx&&(by=bx[bw])){bv=by}if(!bc.test(bv)&&bn.test(bv)){bA=bx.left;e=bz.runtimeStyle&&bz.runtimeStyle.left;if(e){bz.runtimeStyle.left=bz.currentStyle.left}bx.left=bw==="fontSize"?"1em":(bv||0);bv=bx.pixelLeft+"px";bx.left=bA;if(e){bz.runtimeStyle.left=e}}return bv===""?"auto":bv}}Z=aI||aX;function p(by,bw,bv){var bA=bw==="width"?by.offsetWidth:by.offsetHeight,bz=bw==="width"?an:a1,bx=0,e=bz.length;if(bA>0){if(bv!=="border"){for(;bx)<[^<]*)*<\/script>/gi,q=/^(?:select|textarea)/i,h=/\s+/,br=/([?&])_=[^&]*/,K=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,A=b.fn.load,aa={},r={},aE,s,aV=["*/"]+["*"];try{aE=bl.href}catch(aw){aE=av.createElement("a");aE.href="";aE=aE.href}s=K.exec(aE.toLowerCase())||[];function f(e){return function(by,bA){if(typeof by!=="string"){bA=by;by="*"}if(b.isFunction(bA)){var bx=by.toLowerCase().split(h),bw=0,bz=bx.length,bv,bB,bC;for(;bw=0){var e=bw.slice(by,bw.length);bw=bw.slice(0,by)}var bx="GET";if(bz){if(b.isFunction(bz)){bA=bz;bz=L}else{if(typeof bz==="object"){bz=b.param(bz,b.ajaxSettings.traditional);bx="POST"}}}var bv=this;b.ajax({url:bw,type:bx,dataType:"html",data:bz,complete:function(bC,bB,bD){bD=bC.responseText;if(bC.isResolved()){bC.done(function(bE){bD=bE});bv.html(e?b("
").append(bD.replace(a6,"")).find(e):bD)}if(bA){bv.each(bA,[bD,bB,bC])}}});return this},serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?b.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||q.test(this.nodeName)||aZ.test(this.type))}).map(function(e,bv){var bw=b(this).val();return bw==null?null:b.isArray(bw)?b.map(bw,function(by,bx){return{name:bv.name,value:by.replace(bs,"\r\n")}}):{name:bv.name,value:bw.replace(bs,"\r\n")}}).get()}});b.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,bv){b.fn[bv]=function(bw){return this.on(bv,bw)}});b.each(["get","post"],function(e,bv){b[bv]=function(bw,by,bz,bx){if(b.isFunction(by)){bx=bx||bz;bz=by;by=L}return b.ajax({type:bv,url:bw,data:by,success:bz,dataType:bx})}});b.extend({getScript:function(e,bv){return b.get(e,L,bv,"script")},getJSON:function(e,bv,bw){return b.get(e,bv,bw,"json")},ajaxSetup:function(bv,e){if(e){am(bv,b.ajaxSettings)}else{e=bv;bv=b.ajaxSettings}am(bv,e);return bv},ajaxSettings:{url:aE,isLocal:aM.test(s[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":aV},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":bb.String,"text html":true,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:f(aa),ajaxTransport:f(r),ajax:function(bz,bx){if(typeof bz==="object"){bx=bz;bz=L}bx=bx||{};var bD=b.ajaxSetup({},bx),bS=bD.context||bD,bG=bS!==bD&&(bS.nodeType||bS instanceof b)?b(bS):b.event,bR=b.Deferred(),bN=b.Callbacks("once memory"),bB=bD.statusCode||{},bC,bH={},bO={},bQ,by,bL,bE,bI,bA=0,bw,bK,bJ={readyState:0,setRequestHeader:function(bT,bU){if(!bA){var e=bT.toLowerCase();bT=bO[e]=bO[e]||bT;bH[bT]=bU}return this},getAllResponseHeaders:function(){return bA===2?bQ:null},getResponseHeader:function(bT){var e;if(bA===2){if(!by){by={};while((e=aD.exec(bQ))){by[e[1].toLowerCase()]=e[2]}}e=by[bT.toLowerCase()]}return e===L?null:e},overrideMimeType:function(e){if(!bA){bD.mimeType=e}return this},abort:function(e){e=e||"abort";if(bL){bL.abort(e)}bF(0,e);return this}};function bF(bZ,bU,b0,bW){if(bA===2){return}bA=2;if(bE){clearTimeout(bE)}bL=L;bQ=bW||"";bJ.readyState=bZ>0?4:0;var bT,b4,b3,bX=bU,bY=b0?bj(bD,bJ,b0):L,bV,b2;if(bZ>=200&&bZ<300||bZ===304){if(bD.ifModified){if((bV=bJ.getResponseHeader("Last-Modified"))){b.lastModified[bC]=bV}if((b2=bJ.getResponseHeader("Etag"))){b.etag[bC]=b2}}if(bZ===304){bX="notmodified";bT=true}else{try{b4=G(bD,bY);bX="success";bT=true}catch(b1){bX="parsererror";b3=b1}}}else{b3=bX;if(!bX||bZ){bX="error";if(bZ<0){bZ=0}}}bJ.status=bZ;bJ.statusText=""+(bU||bX);if(bT){bR.resolveWith(bS,[b4,bX,bJ])}else{bR.rejectWith(bS,[bJ,bX,b3])}bJ.statusCode(bB);bB=L;if(bw){bG.trigger("ajax"+(bT?"Success":"Error"),[bJ,bD,bT?b4:b3])}bN.fireWith(bS,[bJ,bX]);if(bw){bG.trigger("ajaxComplete",[bJ,bD]);if(!(--b.active)){b.event.trigger("ajaxStop")}}}bR.promise(bJ);bJ.success=bJ.done;bJ.error=bJ.fail;bJ.complete=bN.add;bJ.statusCode=function(bT){if(bT){var e;if(bA<2){for(e in bT){bB[e]=[bB[e],bT[e]]}}else{e=bT[bJ.status];bJ.then(e,e)}}return this};bD.url=((bz||bD.url)+"").replace(bq,"").replace(c,s[1]+"//");bD.dataTypes=b.trim(bD.dataType||"*").toLowerCase().split(h);if(bD.crossDomain==null){bI=K.exec(bD.url.toLowerCase());bD.crossDomain=!!(bI&&(bI[1]!=s[1]||bI[2]!=s[2]||(bI[3]||(bI[1]==="http:"?80:443))!=(s[3]||(s[1]==="http:"?80:443))))}if(bD.data&&bD.processData&&typeof bD.data!=="string"){bD.data=b.param(bD.data,bD.traditional)}aW(aa,bD,bx,bJ);if(bA===2){return false}bw=bD.global;bD.type=bD.type.toUpperCase();bD.hasContent=!aQ.test(bD.type);if(bw&&b.active++===0){b.event.trigger("ajaxStart")}if(!bD.hasContent){if(bD.data){bD.url+=(M.test(bD.url)?"&":"?")+bD.data;delete bD.data}bC=bD.url;if(bD.cache===false){var bv=b.now(),bP=bD.url.replace(br,"$1_="+bv);bD.url=bP+((bP===bD.url)?(M.test(bD.url)?"&":"?")+"_="+bv:"")}}if(bD.data&&bD.hasContent&&bD.contentType!==false||bx.contentType){bJ.setRequestHeader("Content-Type",bD.contentType)}if(bD.ifModified){bC=bC||bD.url;if(b.lastModified[bC]){bJ.setRequestHeader("If-Modified-Since",b.lastModified[bC])}if(b.etag[bC]){bJ.setRequestHeader("If-None-Match",b.etag[bC])}}bJ.setRequestHeader("Accept",bD.dataTypes[0]&&bD.accepts[bD.dataTypes[0]]?bD.accepts[bD.dataTypes[0]]+(bD.dataTypes[0]!=="*"?", "+aV+"; q=0.01":""):bD.accepts["*"]);for(bK in bD.headers){bJ.setRequestHeader(bK,bD.headers[bK])}if(bD.beforeSend&&(bD.beforeSend.call(bS,bJ,bD)===false||bA===2)){bJ.abort();return false}for(bK in {success:1,error:1,complete:1}){bJ[bK](bD[bK])}bL=aW(r,bD,bx,bJ);if(!bL){bF(-1,"No Transport")}else{bJ.readyState=1;if(bw){bG.trigger("ajaxSend",[bJ,bD])}if(bD.async&&bD.timeout>0){bE=setTimeout(function(){bJ.abort("timeout")},bD.timeout)}try{bA=1;bL.send(bH,bF)}catch(bM){if(bA<2){bF(-1,bM)}else{throw bM}}}return bJ},param:function(e,bw){var bv=[],by=function(bz,bA){bA=b.isFunction(bA)?bA():bA;bv[bv.length]=encodeURIComponent(bz)+"="+encodeURIComponent(bA)};if(bw===L){bw=b.ajaxSettings.traditional}if(b.isArray(e)||(e.jquery&&!b.isPlainObject(e))){b.each(e,function(){by(this.name,this.value)})}else{for(var bx in e){v(bx,e[bx],bw,by)}}return bv.join("&").replace(k,"+")}});function v(bw,by,bv,bx){if(b.isArray(by)){b.each(by,function(bA,bz){if(bv||ap.test(bw)){bx(bw,bz)}else{v(bw+"["+(typeof bz==="object"||b.isArray(bz)?bA:"")+"]",bz,bv,bx)}})}else{if(!bv&&by!=null&&typeof by==="object"){for(var e in by){v(bw+"["+e+"]",by[e],bv,bx)}}else{bx(bw,by)}}}b.extend({active:0,lastModified:{},etag:{}});function bj(bD,bC,bz){var bv=bD.contents,bB=bD.dataTypes,bw=bD.responseFields,by,bA,bx,e;for(bA in bw){if(bA in bz){bC[bw[bA]]=bz[bA]}}while(bB[0]==="*"){bB.shift();if(by===L){by=bD.mimeType||bC.getResponseHeader("content-type")}}if(by){for(bA in bv){if(bv[bA]&&bv[bA].test(by)){bB.unshift(bA);break}}}if(bB[0] in bz){bx=bB[0]}else{for(bA in bz){if(!bB[0]||bD.converters[bA+" "+bB[0]]){bx=bA;break}if(!e){e=bA}}bx=bx||e}if(bx){if(bx!==bB[0]){bB.unshift(bx)}return bz[bx]}}function G(bH,bz){if(bH.dataFilter){bz=bH.dataFilter(bz,bH.dataType)}var bD=bH.dataTypes,bG={},bA,bE,bw=bD.length,bB,bC=bD[0],bx,by,bF,bv,e;for(bA=1;bA=bw.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();bw.animatedProperties[this.prop]=true;for(bA in bw.animatedProperties){if(bw.animatedProperties[bA]!==true){e=false}}if(e){if(bw.overflow!=null&&!b.support.shrinkWrapBlocks){b.each(["","X","Y"],function(bC,bD){bz.style["overflow"+bD]=bw.overflow[bC]})}if(bw.hide){b(bz).hide()}if(bw.hide||bw.show){for(bA in bw.animatedProperties){b.style(bz,bA,bw.orig[bA]);b.removeData(bz,"fxshow"+bA,true);b.removeData(bz,"toggle"+bA,true)}}bv=bw.complete;if(bv){bw.complete=false;bv.call(bz)}}return false}else{if(bw.duration==Infinity){this.now=bx}else{bB=bx-this.startTime;this.state=bB/bw.duration;this.pos=b.easing[bw.animatedProperties[this.prop]](this.state,bB,0,1,bw.duration);this.now=this.start+((this.end-this.start)*this.pos)}this.update()}return true}};b.extend(b.fx,{tick:function(){var bw,bv=b.timers,e=0;for(;e").appendTo(e),bw=bv.css("display");bv.remove();if(bw==="none"||bw===""){if(!a8){a8=av.createElement("iframe");a8.frameBorder=a8.width=a8.height=0}e.appendChild(a8);if(!m||!a8.createElement){m=(a8.contentWindow||a8.contentDocument).document;m.write((av.compatMode==="CSS1Compat"?"":"")+"");m.close()}bv=m.createElement(bx);m.body.appendChild(bv);bw=b.css(bv,"display");e.removeChild(a8)}Q[bx]=bw}return Q[bx]}var V=/^t(?:able|d|h)$/i,ad=/^(?:body|html)$/i;if("getBoundingClientRect" in av.documentElement){b.fn.offset=function(bI){var by=this[0],bB;if(bI){return this.each(function(e){b.offset.setOffset(this,bI,e)})}if(!by||!by.ownerDocument){return null}if(by===by.ownerDocument.body){return b.offset.bodyOffset(by)}try{bB=by.getBoundingClientRect()}catch(bF){}var bH=by.ownerDocument,bw=bH.documentElement;if(!bB||!b.contains(bw,by)){return bB?{top:bB.top,left:bB.left}:{top:0,left:0}}var bC=bH.body,bD=aK(bH),bA=bw.clientTop||bC.clientTop||0,bE=bw.clientLeft||bC.clientLeft||0,bv=bD.pageYOffset||b.support.boxModel&&bw.scrollTop||bC.scrollTop,bz=bD.pageXOffset||b.support.boxModel&&bw.scrollLeft||bC.scrollLeft,bG=bB.top+bv-bA,bx=bB.left+bz-bE;return{top:bG,left:bx}}}else{b.fn.offset=function(bF){var bz=this[0];if(bF){return this.each(function(bG){b.offset.setOffset(this,bF,bG)})}if(!bz||!bz.ownerDocument){return null}if(bz===bz.ownerDocument.body){return b.offset.bodyOffset(bz)}var bC,bw=bz.offsetParent,bv=bz,bE=bz.ownerDocument,bx=bE.documentElement,bA=bE.body,bB=bE.defaultView,e=bB?bB.getComputedStyle(bz,null):bz.currentStyle,bD=bz.offsetTop,by=bz.offsetLeft;while((bz=bz.parentNode)&&bz!==bA&&bz!==bx){if(b.support.fixedPosition&&e.position==="fixed"){break}bC=bB?bB.getComputedStyle(bz,null):bz.currentStyle;bD-=bz.scrollTop;by-=bz.scrollLeft;if(bz===bw){bD+=bz.offsetTop;by+=bz.offsetLeft;if(b.support.doesNotAddBorder&&!(b.support.doesAddBorderForTableAndCells&&V.test(bz.nodeName))){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}bv=bw;bw=bz.offsetParent}if(b.support.subtractsBorderForOverflowNotVisible&&bC.overflow!=="visible"){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}e=bC}if(e.position==="relative"||e.position==="static"){bD+=bA.offsetTop;by+=bA.offsetLeft}if(b.support.fixedPosition&&e.position==="fixed"){bD+=Math.max(bx.scrollTop,bA.scrollTop);by+=Math.max(bx.scrollLeft,bA.scrollLeft)}return{top:bD,left:by}}}b.offset={bodyOffset:function(e){var bw=e.offsetTop,bv=e.offsetLeft;if(b.support.doesNotIncludeMarginInBodyOffset){bw+=parseFloat(b.css(e,"marginTop"))||0;bv+=parseFloat(b.css(e,"marginLeft"))||0}return{top:bw,left:bv}},setOffset:function(bx,bG,bA){var bB=b.css(bx,"position");if(bB==="static"){bx.style.position="relative"}var bz=b(bx),bv=bz.offset(),e=b.css(bx,"top"),bE=b.css(bx,"left"),bF=(bB==="absolute"||bB==="fixed")&&b.inArray("auto",[e,bE])>-1,bD={},bC={},bw,by;if(bF){bC=bz.position();bw=bC.top;by=bC.left}else{bw=parseFloat(e)||0;by=parseFloat(bE)||0}if(b.isFunction(bG)){bG=bG.call(bx,bA,bv)}if(bG.top!=null){bD.top=(bG.top-bv.top)+bw}if(bG.left!=null){bD.left=(bG.left-bv.left)+by}if("using" in bG){bG.using.call(bx,bD)}else{bz.css(bD)}}};b.fn.extend({position:function(){if(!this[0]){return null}var bw=this[0],bv=this.offsetParent(),bx=this.offset(),e=ad.test(bv[0].nodeName)?{top:0,left:0}:bv.offset();bx.top-=parseFloat(b.css(bw,"marginTop"))||0;bx.left-=parseFloat(b.css(bw,"marginLeft"))||0;e.top+=parseFloat(b.css(bv[0],"borderTopWidth"))||0;e.left+=parseFloat(b.css(bv[0],"borderLeftWidth"))||0;return{top:bx.top-e.top,left:bx.left-e.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||av.body;while(e&&(!ad.test(e.nodeName)&&b.css(e,"position")==="static")){e=e.offsetParent}return e})}});b.each(["Left","Top"],function(bv,e){var bw="scroll"+e;b.fn[bw]=function(bz){var bx,by;if(bz===L){bx=this[0];if(!bx){return null}by=aK(bx);return by?("pageXOffset" in by)?by[bv?"pageYOffset":"pageXOffset"]:b.support.boxModel&&by.document.documentElement[bw]||by.document.body[bw]:bx[bw]}return this.each(function(){by=aK(this);if(by){by.scrollTo(!bv?bz:b(by).scrollLeft(),bv?bz:b(by).scrollTop())}else{this[bw]=bz}})}});function aK(e){return b.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:false}b.each(["Height","Width"],function(bv,e){var bw=e.toLowerCase();b.fn["inner"+e]=function(){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,"padding")):this[bw]():null};b.fn["outer"+e]=function(by){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,by?"margin":"border")):this[bw]():null};b.fn[bw]=function(bz){var bA=this[0];if(!bA){return bz==null?null:this}if(b.isFunction(bz)){return this.each(function(bE){var bD=b(this);bD[bw](bz.call(this,bE,bD[bw]()))})}if(b.isWindow(bA)){var bB=bA.document.documentElement["client"+e],bx=bA.document.body;return bA.document.compatMode==="CSS1Compat"&&bB||bx&&bx["client"+e]||bB}else{if(bA.nodeType===9){return Math.max(bA.documentElement["client"+e],bA.body["scroll"+e],bA.documentElement["scroll"+e],bA.body["offset"+e],bA.documentElement["offset"+e])}else{if(bz===L){var bC=b.css(bA,bw),by=parseFloat(bC);return b.isNumeric(by)?by:bC}else{return this.css(bw,typeof bz==="string"?bz:bz+"px")}}}}});bb.jQuery=bb.$=b;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return b})}})(window);/*! - * jQuery UI 1.8.18 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI - */ -(function(a,d){a.ui=a.ui||{};if(a.ui.version){return}a.extend(a.ui,{version:"1.8.18",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(e,f){return typeof e==="number"?this.each(function(){var g=this;setTimeout(function(){a(g).focus();if(f){f.call(g)}},e)}):this._focus.apply(this,arguments)},scrollParent:function(){var e;if((a.browser.msie&&(/(static|relative)/).test(this.css("position")))||(/absolute/).test(this.css("position"))){e=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test(a.curCSS(this,"position",1))&&(/(auto|scroll)/).test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0)}else{e=this.parents().filter(function(){return(/(auto|scroll)/).test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0)}return(/fixed/).test(this.css("position"))||!e.length?a(document):e},zIndex:function(h){if(h!==d){return this.css("zIndex",h)}if(this.length){var f=a(this[0]),e,g;while(f.length&&f[0]!==document){e=f.css("position");if(e==="absolute"||e==="relative"||e==="fixed"){g=parseInt(f.css("zIndex"),10);if(!isNaN(g)&&g!==0){return g}}f=f.parent()}}return 0},disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});a.each(["Width","Height"],function(g,e){var f=e==="Width"?["Left","Right"]:["Top","Bottom"],h=e.toLowerCase(),k={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};function j(m,l,i,n){a.each(f,function(){l-=parseFloat(a.curCSS(m,"padding"+this,true))||0;if(i){l-=parseFloat(a.curCSS(m,"border"+this+"Width",true))||0}if(n){l-=parseFloat(a.curCSS(m,"margin"+this,true))||0}});return l}a.fn["inner"+e]=function(i){if(i===d){return k["inner"+e].call(this)}return this.each(function(){a(this).css(h,j(this,i)+"px")})};a.fn["outer"+e]=function(i,l){if(typeof i!=="number"){return k["outer"+e].call(this,i)}return this.each(function(){a(this).css(h,j(this,i,true,l)+"px")})}});function c(g,e){var j=g.nodeName.toLowerCase();if("area"===j){var i=g.parentNode,h=i.name,f;if(!g.href||!h||i.nodeName.toLowerCase()!=="map"){return false}f=a("img[usemap=#"+h+"]")[0];return !!f&&b(f)}return(/input|select|textarea|button|object/.test(j)?!g.disabled:"a"==j?g.href||e:e)&&b(g)}function b(e){return !a(e).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}a.extend(a.expr[":"],{data:function(g,f,e){return !!a.data(g,e[3])},focusable:function(e){return c(e,!isNaN(a.attr(e,"tabindex")))},tabbable:function(g){var e=a.attr(g,"tabindex"),f=isNaN(e);return(f||e>=0)&&c(g,!f)}});a(function(){var e=document.body,f=e.appendChild(f=document.createElement("div"));f.offsetHeight;a.extend(f.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});a.support.minHeight=f.offsetHeight===100;a.support.selectstart="onselectstart" in f;e.removeChild(f).style.display="none"});a.extend(a.ui,{plugin:{add:function(f,g,j){var h=a.ui[f].prototype;for(var e in j){h.plugins[e]=h.plugins[e]||[];h.plugins[e].push([g,j[e]])}},call:function(e,g,f){var j=e.plugins[g];if(!j||!e.element[0].parentNode){return}for(var h=0;h0){return true}h[e]=1;g=(h[e]>0);h[e]=0;return g},isOverAxis:function(f,e,g){return(f>e)&&(f<(e+g))},isOver:function(j,f,i,h,e,g){return a.ui.isOverAxis(j,i,e)&&a.ui.isOverAxis(f,h,g)}})})(jQuery);/*! - * jQuery UI Widget 1.8.18 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Widget - */ -(function(b,d){if(b.cleanData){var c=b.cleanData;b.cleanData=function(f){for(var g=0,h;(h=f[g])!=null;g++){try{b(h).triggerHandler("remove")}catch(j){}}c(f)}}else{var a=b.fn.remove;b.fn.remove=function(e,f){return this.each(function(){if(!f){if(!e||b.filter(e,[this]).length){b("*",this).add([this]).each(function(){try{b(this).triggerHandler("remove")}catch(g){}})}}return a.call(b(this),e,f)})}}b.widget=function(f,h,e){var g=f.split(".")[0],j;f=f.split(".")[1];j=g+"-"+f;if(!e){e=h;h=b.Widget}b.expr[":"][j]=function(k){return !!b.data(k,f)};b[g]=b[g]||{};b[g][f]=function(k,l){if(arguments.length){this._createWidget(k,l)}};var i=new h();i.options=b.extend(true,{},i.options);b[g][f].prototype=b.extend(true,i,{namespace:g,widgetName:f,widgetEventPrefix:b[g][f].prototype.widgetEventPrefix||f,widgetBaseClass:j},e);b.widget.bridge(f,b[g][f])};b.widget.bridge=function(f,e){b.fn[f]=function(i){var g=typeof i==="string",h=Array.prototype.slice.call(arguments,1),j=this;i=!g&&h.length?b.extend.apply(null,[true,i].concat(h)):i;if(g&&i.charAt(0)==="_"){return j}if(g){this.each(function(){var k=b.data(this,f),l=k&&b.isFunction(k[i])?k[i].apply(k,h):k;if(l!==k&&l!==d){j=l;return false}})}else{this.each(function(){var k=b.data(this,f);if(k){k.option(i||{})._init()}else{b.data(this,f,new e(i,this))}})}return j}};b.Widget=function(e,f){if(arguments.length){this._createWidget(e,f)}};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(f,g){b.data(g,this.widgetName,this);this.element=b(g);this.options=b.extend(true,{},this.options,this._getCreateOptions(),f);var e=this;this.element.bind("remove."+this.widgetName,function(){e.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){return b.metadata&&b.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(f,g){var e=f;if(arguments.length===0){return b.extend({},this.options)}if(typeof f==="string"){if(g===d){return this.options[f]}e={};e[f]=g}this._setOptions(e);return this},_setOptions:function(f){var e=this;b.each(f,function(g,h){e._setOption(g,h)});return this},_setOption:function(e,f){this.options[e]=f;if(e==="disabled"){this.widget()[f?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",f)}return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(e,f,g){var j,i,h=this.options[e];g=g||{};f=b.Event(f);f.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase();f.target=this.element[0];i=f.originalEvent;if(i){for(j in i){if(!(j in f)){f[j]=i[j]}}}this.element.trigger(f,g);return !(b.isFunction(h)&&h.call(this.element[0],f,g)===false||f.isDefaultPrevented())}}})(jQuery);/*! - * jQuery UI Mouse 1.8.18 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Mouse - * - * Depends: - * jquery.ui.widget.js - */ -(function(b,c){var a=false;b(document).mouseup(function(d){a=false});b.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var d=this;this.element.bind("mousedown."+this.widgetName,function(e){return d._mouseDown(e)}).bind("click."+this.widgetName,function(e){if(true===b.data(e.target,d.widgetName+".preventClickEvent")){b.removeData(e.target,d.widgetName+".preventClickEvent");e.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(f){if(a){return}(this._mouseStarted&&this._mouseUp(f));this._mouseDownEvent=f;var e=this,g=(f.which==1),d=(typeof this.options.cancel=="string"&&f.target.nodeName?b(f.target).closest(this.options.cancel).length:false);if(!g||d||!this._mouseCapture(f)){return true}this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){e.mouseDelayMet=true},this.options.delay)}if(this._mouseDistanceMet(f)&&this._mouseDelayMet(f)){this._mouseStarted=(this._mouseStart(f)!==false);if(!this._mouseStarted){f.preventDefault();return true}}if(true===b.data(f.target,this.widgetName+".preventClickEvent")){b.removeData(f.target,this.widgetName+".preventClickEvent")}this._mouseMoveDelegate=function(h){return e._mouseMove(h)};this._mouseUpDelegate=function(h){return e._mouseUp(h)};b(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);f.preventDefault();a=true;return true},_mouseMove:function(d){if(b.browser.msie&&!(document.documentMode>=9)&&!d.button){return this._mouseUp(d)}if(this._mouseStarted){this._mouseDrag(d);return d.preventDefault()}if(this._mouseDistanceMet(d)&&this._mouseDelayMet(d)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,d)!==false);(this._mouseStarted?this._mouseDrag(d):this._mouseUp(d))}return !this._mouseStarted},_mouseUp:function(d){b(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;if(d.target==this._mouseDownEvent.target){b.data(d.target,this.widgetName+".preventClickEvent",true)}this._mouseStop(d)}return false},_mouseDistanceMet:function(d){return(Math.max(Math.abs(this._mouseDownEvent.pageX-d.pageX),Math.abs(this._mouseDownEvent.pageY-d.pageY))>=this.options.distance)},_mouseDelayMet:function(d){return this.mouseDelayMet},_mouseStart:function(d){},_mouseDrag:function(d){},_mouseStop:function(d){},_mouseCapture:function(d){return true}})})(jQuery);(function(c,d){c.widget("ui.resizable",c.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,containment:false,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1000},_create:function(){var f=this,k=this.options;this.element.addClass("ui-resizable");c.extend(this,{_aspectRatio:!!(k.aspectRatio),aspectRatio:k.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:k.helper||k.ghost||k.animate?k.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){this.element.wrap(c('
').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=k.handles||(!c(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all"){this.handles="n,e,s,w,se,sw,ne,nw"}var l=this.handles.split(",");this.handles={};for(var g=0;g
');if(/sw|se|ne|nw/.test(j)){h.css({zIndex:++k.zIndex})}if("se"==j){h.addClass("ui-icon ui-icon-gripsmall-diagonal-se")}this.handles[j]=".ui-resizable-"+j;this.element.append(h)}}this._renderAxis=function(q){q=q||this.element;for(var n in this.handles){if(this.handles[n].constructor==String){this.handles[n]=c(this.handles[n],this.element).show()}if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var o=c(this.handles[n],this.element),p=0;p=/sw|ne|nw|se|n|s/.test(n)?o.outerHeight():o.outerWidth();var m=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join("");q.css(m,p);this._proportionallyResize()}if(!c(this.handles[n]).length){continue}}};this._renderAxis(this.element);this._handles=c(".ui-resizable-handle",this.element).disableSelection();this._handles.mouseover(function(){if(!f.resizing){if(this.className){var i=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)}f.axis=i&&i[1]?i[1]:"se"}});if(k.autoHide){this._handles.hide();c(this.element).addClass("ui-resizable-autohide").hover(function(){if(k.disabled){return}c(this).removeClass("ui-resizable-autohide");f._handles.show()},function(){if(k.disabled){return}if(!f.resizing){c(this).addClass("ui-resizable-autohide");f._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var e=function(g){c(g).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){e(this.element);var f=this.element;f.after(this.originalElement.css({position:f.css("position"),width:f.outerWidth(),height:f.outerHeight(),top:f.css("top"),left:f.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);e(this.originalElement);return this},_mouseCapture:function(f){var g=false;for(var e in this.handles){if(c(this.handles[e])[0]==f.target){g=true}}return !this.options.disabled&&g},_mouseStart:function(g){var j=this.options,f=this.element.position(),e=this.element;this.resizing=true;this.documentScroll={top:c(document).scrollTop(),left:c(document).scrollLeft()};if(e.is(".ui-draggable")||(/absolute/).test(e.css("position"))){e.css({position:"absolute",top:f.top,left:f.left})}this._renderProxy();var k=b(this.helper.css("left")),h=b(this.helper.css("top"));if(j.containment){k+=c(j.containment).scrollLeft()||0;h+=c(j.containment).scrollTop()||0}this.offset=this.helper.offset();this.position={left:k,top:h};this.size=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalSize=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalPosition={left:k,top:h};this.sizeDiff={width:e.outerWidth()-e.width(),height:e.outerHeight()-e.height()};this.originalMousePosition={left:g.pageX,top:g.pageY};this.aspectRatio=(typeof j.aspectRatio=="number")?j.aspectRatio:((this.originalSize.width/this.originalSize.height)||1);var i=c(".ui-resizable-"+this.axis).css("cursor");c("body").css("cursor",i=="auto"?this.axis+"-resize":i);e.addClass("ui-resizable-resizing");this._propagate("start",g);return true},_mouseDrag:function(e){var h=this.helper,g=this.options,m={},q=this,j=this.originalMousePosition,n=this.axis;var r=(e.pageX-j.left)||0,p=(e.pageY-j.top)||0;var i=this._change[n];if(!i){return false}var l=i.apply(this,[e,r,p]),k=c.browser.msie&&c.browser.version<7,f=this.sizeDiff;this._updateVirtualBoundaries(e.shiftKey);if(this._aspectRatio||e.shiftKey){l=this._updateRatio(l,e)}l=this._respectSize(l,e);this._propagate("resize",e);h.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});if(!this._helper&&this._proportionallyResizeElements.length){this._proportionallyResize()}this._updateCache(l);this._trigger("resize",e,this.ui());return false},_mouseStop:function(h){this.resizing=false;var i=this.options,m=this;if(this._helper){var g=this._proportionallyResizeElements,e=g.length&&(/textarea/i).test(g[0].nodeName),f=e&&c.ui.hasScroll(g[0],"left")?0:m.sizeDiff.height,k=e?0:m.sizeDiff.width;var n={width:(m.helper.width()-k),height:(m.helper.height()-f)},j=(parseInt(m.element.css("left"),10)+(m.position.left-m.originalPosition.left))||null,l=(parseInt(m.element.css("top"),10)+(m.position.top-m.originalPosition.top))||null;if(!i.animate){this.element.css(c.extend(n,{top:l,left:j}))}m.helper.height(m.size.height);m.helper.width(m.size.width);if(this._helper&&!i.animate){this._proportionallyResize()}}c("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",h);if(this._helper){this.helper.remove()}return false},_updateVirtualBoundaries:function(g){var j=this.options,i,h,f,k,e;e={minWidth:a(j.minWidth)?j.minWidth:0,maxWidth:a(j.maxWidth)?j.maxWidth:Infinity,minHeight:a(j.minHeight)?j.minHeight:0,maxHeight:a(j.maxHeight)?j.maxHeight:Infinity};if(this._aspectRatio||g){i=e.minHeight*this.aspectRatio;f=e.minWidth/this.aspectRatio;h=e.maxHeight*this.aspectRatio;k=e.maxWidth/this.aspectRatio;if(i>e.minWidth){e.minWidth=i}if(f>e.minHeight){e.minHeight=f}if(hl.width),s=a(l.height)&&i.minHeight&&(i.minHeight>l.height);if(h){l.width=i.minWidth}if(s){l.height=i.minHeight}if(t){l.width=i.maxWidth}if(m){l.height=i.maxHeight}var f=this.originalPosition.left+this.originalSize.width,p=this.position.top+this.size.height;var k=/sw|nw|w/.test(q),e=/nw|ne|n/.test(q);if(h&&k){l.left=f-i.minWidth}if(t&&k){l.left=f-i.maxWidth}if(s&&e){l.top=p-i.minHeight}if(m&&e){l.top=p-i.maxHeight}var n=!l.width&&!l.height;if(n&&!l.left&&l.top){l.top=null}else{if(n&&!l.top&&l.left){l.left=null}}return l},_proportionallyResize:function(){var k=this.options;if(!this._proportionallyResizeElements.length){return}var g=this.helper||this.element;for(var f=0;f');var e=c.browser.msie&&c.browser.version<7,g=(e?1:0),h=(e?2:-1);this.helper.addClass(this._helper).css({width:this.element.outerWidth()+h,height:this.element.outerHeight()+h,position:"absolute",left:this.elementOffset.left-g+"px",top:this.elementOffset.top-g+"px",zIndex:++i.zIndex});this.helper.appendTo("body").disableSelection()}else{this.helper=this.element}},_change:{e:function(g,f,e){return{width:this.originalSize.width+f}},w:function(h,f,e){var j=this.options,g=this.originalSize,i=this.originalPosition;return{left:i.left+f,width:g.width-f}},n:function(h,f,e){var j=this.options,g=this.originalSize,i=this.originalPosition;return{top:i.top+e,height:g.height-e}},s:function(g,f,e){return{height:this.originalSize.height+e}},se:function(g,f,e){return c.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[g,f,e]))},sw:function(g,f,e){return c.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[g,f,e]))},ne:function(g,f,e){return c.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[g,f,e]))},nw:function(g,f,e){return c.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[g,f,e]))}},_propagate:function(f,e){c.ui.plugin.call(this,f,[e,this.ui()]);(f!="resize"&&this._trigger(f,e,this.ui()))},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});c.extend(c.ui.resizable,{version:"1.8.18"});c.ui.plugin.add("resizable","alsoResize",{start:function(f,g){var e=c(this).data("resizable"),i=e.options;var h=function(j){c(j).each(function(){var k=c(this);k.data("resizable-alsoresize",{width:parseInt(k.width(),10),height:parseInt(k.height(),10),left:parseInt(k.css("left"),10),top:parseInt(k.css("top"),10)})})};if(typeof(i.alsoResize)=="object"&&!i.alsoResize.parentNode){if(i.alsoResize.length){i.alsoResize=i.alsoResize[0];h(i.alsoResize)}else{c.each(i.alsoResize,function(j){h(j)})}}else{h(i.alsoResize)}},resize:function(g,i){var f=c(this).data("resizable"),j=f.options,h=f.originalSize,l=f.originalPosition;var k={height:(f.size.height-h.height)||0,width:(f.size.width-h.width)||0,top:(f.position.top-l.top)||0,left:(f.position.left-l.left)||0},e=function(m,n){c(m).each(function(){var q=c(this),r=c(this).data("resizable-alsoresize"),p={},o=n&&n.length?n:q.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];c.each(o,function(s,u){var t=(r[u]||0)+(k[u]||0);if(t&&t>=0){p[u]=t||null}});q.css(p)})};if(typeof(j.alsoResize)=="object"&&!j.alsoResize.nodeType){c.each(j.alsoResize,function(m,n){e(m,n)})}else{e(j.alsoResize)}},stop:function(e,f){c(this).removeData("resizable-alsoresize")}});c.ui.plugin.add("resizable","animate",{stop:function(i,n){var p=c(this).data("resizable"),j=p.options;var h=p._proportionallyResizeElements,e=h.length&&(/textarea/i).test(h[0].nodeName),f=e&&c.ui.hasScroll(h[0],"left")?0:p.sizeDiff.height,l=e?0:p.sizeDiff.width;var g={width:(p.size.width-l),height:(p.size.height-f)},k=(parseInt(p.element.css("left"),10)+(p.position.left-p.originalPosition.left))||null,m=(parseInt(p.element.css("top"),10)+(p.position.top-p.originalPosition.top))||null;p.element.animate(c.extend(g,m&&k?{top:m,left:k}:{}),{duration:j.animateDuration,easing:j.animateEasing,step:function(){var o={width:parseInt(p.element.css("width"),10),height:parseInt(p.element.css("height"),10),top:parseInt(p.element.css("top"),10),left:parseInt(p.element.css("left"),10)};if(h&&h.length){c(h[0]).css({width:o.width,height:o.height})}p._updateCache(o);p._propagate("resize",i)}})}});c.ui.plugin.add("resizable","containment",{start:function(f,r){var t=c(this).data("resizable"),j=t.options,l=t.element;var g=j.containment,k=(g instanceof c)?g.get(0):(/parent/.test(g))?l.parent().get(0):g;if(!k){return}t.containerElement=c(k);if(/document/.test(g)||g==document){t.containerOffset={left:0,top:0};t.containerPosition={left:0,top:0};t.parentData={element:c(document),left:0,top:0,width:c(document).width(),height:c(document).height()||document.body.parentNode.scrollHeight}}else{var n=c(k),i=[];c(["Top","Right","Left","Bottom"]).each(function(p,o){i[p]=b(n.css("padding"+o))});t.containerOffset=n.offset();t.containerPosition=n.position();t.containerSize={height:(n.innerHeight()-i[3]),width:(n.innerWidth()-i[1])};var q=t.containerOffset,e=t.containerSize.height,m=t.containerSize.width,h=(c.ui.hasScroll(k,"left")?k.scrollWidth:m),s=(c.ui.hasScroll(k)?k.scrollHeight:e);t.parentData={element:k,left:q.left,top:q.top,width:h,height:s}}},resize:function(g,q){var t=c(this).data("resizable"),i=t.options,f=t.containerSize,p=t.containerOffset,m=t.size,n=t.position,r=t._aspectRatio||g.shiftKey,e={top:0,left:0},h=t.containerElement;if(h[0]!=document&&(/static/).test(h.css("position"))){e=p}if(n.left<(t._helper?p.left:0)){t.size.width=t.size.width+(t._helper?(t.position.left-p.left):(t.position.left-e.left));if(r){t.size.height=t.size.width/i.aspectRatio}t.position.left=i.helper?p.left:0}if(n.top<(t._helper?p.top:0)){t.size.height=t.size.height+(t._helper?(t.position.top-p.top):t.position.top);if(r){t.size.width=t.size.height*i.aspectRatio}t.position.top=t._helper?p.top:0}t.offset.left=t.parentData.left+t.position.left;t.offset.top=t.parentData.top+t.position.top;var l=Math.abs((t._helper?t.offset.left-e.left:(t.offset.left-e.left))+t.sizeDiff.width),s=Math.abs((t._helper?t.offset.top-e.top:(t.offset.top-p.top))+t.sizeDiff.height);var k=t.containerElement.get(0)==t.element.parent().get(0),j=/relative|absolute/.test(t.containerElement.css("position"));if(k&&j){l-=t.parentData.left}if(l+t.size.width>=t.parentData.width){t.size.width=t.parentData.width-l;if(r){t.size.height=t.size.width/t.aspectRatio}}if(s+t.size.height>=t.parentData.height){t.size.height=t.parentData.height-s;if(r){t.size.width=t.size.height*t.aspectRatio}}},stop:function(f,n){var q=c(this).data("resizable"),g=q.options,l=q.position,m=q.containerOffset,e=q.containerPosition,i=q.containerElement;var j=c(q.helper),r=j.offset(),p=j.outerWidth()-q.sizeDiff.width,k=j.outerHeight()-q.sizeDiff.height;if(q._helper&&!g.animate&&(/relative/).test(i.css("position"))){c(this).css({left:r.left-e.left-m.left,width:p,height:k})}if(q._helper&&!g.animate&&(/static/).test(i.css("position"))){c(this).css({left:r.left-e.left-m.left,width:p,height:k})}}});c.ui.plugin.add("resizable","ghost",{start:function(g,h){var e=c(this).data("resizable"),i=e.options,f=e.size;e.ghost=e.originalElement.clone();e.ghost.css({opacity:0.25,display:"block",position:"relative",height:f.height,width:f.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof i.ghost=="string"?i.ghost:"");e.ghost.appendTo(e.helper)},resize:function(f,g){var e=c(this).data("resizable"),h=e.options;if(e.ghost){e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})}},stop:function(f,g){var e=c(this).data("resizable"),h=e.options;if(e.ghost&&e.helper){e.helper.get(0).removeChild(e.ghost.get(0))}}});c.ui.plugin.add("resizable","grid",{resize:function(e,m){var p=c(this).data("resizable"),h=p.options,k=p.size,i=p.originalSize,j=p.originalPosition,n=p.axis,l=h._aspectRatio||e.shiftKey;h.grid=typeof h.grid=="number"?[h.grid,h.grid]:h.grid;var g=Math.round((k.width-i.width)/(h.grid[0]||1))*(h.grid[0]||1),f=Math.round((k.height-i.height)/(h.grid[1]||1))*(h.grid[1]||1);if(/^(se|s|e)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f}else{if(/^(ne)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f;p.position.top=j.top-f}else{if(/^(sw)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f;p.position.left=j.left-g}else{p.size.width=i.width+g;p.size.height=i.height+f;p.position.top=j.top-f;p.position.left=j.left-g}}}}});var b=function(e){return parseInt(e,10)||0};var a=function(e){return !isNaN(parseInt(e,10))}})(jQuery);/*! - * jQuery hashchange event - v1.3 - 7/21/2010 - * http://benalman.com/projects/jquery-hashchange-plugin/ - * - * Copyright (c) 2010 "Cowboy" Ben Alman - * Dual licensed under the MIT and GPL licenses. - * http://benalman.com/about/license/ - */ -(function($,e,b){var c="hashchange",h=document,f,g=$.event.special,i=h.documentMode,d="on"+c in e&&(i===b||i>7);function a(j){j=j||location.href;return"#"+j.replace(/^[^#]*#?(.*)$/,"$1")}$.fn[c]=function(j){return j?this.bind(c,j):this.trigger(c)};$.fn[c].delay=50;g[c]=$.extend(g[c],{setup:function(){if(d){return false}$(f.start)},teardown:function(){if(d){return false}$(f.stop)}});f=(function(){var j={},p,m=a(),k=function(q){return q},l=k,o=k;j.start=function(){p||n()};j.stop=function(){p&&clearTimeout(p);p=b};function n(){var r=a(),q=o(m);if(r!==m){l(m=r,q);$(e).trigger(c)}else{if(q!==m){location.href=location.href.replace(/#.*/,"")+q}}p=setTimeout(n,$.fn[c].delay)}$.browser.msie&&!d&&(function(){var q,r;j.start=function(){if(!q){r=$.fn[c].src;r=r&&r+a();q=$('