mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
opal: fix node-type
This commit is contained in:
parent
9768014a06
commit
8e53d2a329
8 changed files with 256 additions and 119 deletions
|
@ -158,7 +158,7 @@ cmake_dependent_option(WITH_NODE_LOOPBACK "Build with loopback node-type"
|
|||
cmake_dependent_option(WITH_NODE_MQTT "Build with mqtt node-type" ON "MOSQUITTO_FOUND" OFF)
|
||||
cmake_dependent_option(WITH_NODE_NANOMSG "Build with nanomsg node-type" ON "NANOMSG_FOUND" OFF)
|
||||
cmake_dependent_option(WITH_NODE_NGSI "Build with ngsi node-type" ON "" OFF)
|
||||
cmake_dependent_option(WITH_NODE_OPAL "Build with opal node-type" ON "BUILD32; Opal_FOUND" OFF)
|
||||
cmake_dependent_option(WITH_NODE_OPAL "Build with opal node-type" ON "Opal_FOUND" OFF)
|
||||
cmake_dependent_option(WITH_NODE_RTP "Build with rtp node-type" ON "RE_FOUND" OFF)
|
||||
cmake_dependent_option(WITH_NODE_SHMEM "Build with shmem node-type" ON "HAS_SEMAPHORE; HAS_MMAN" OFF)
|
||||
cmake_dependent_option(WITH_NODE_SIGNAL "Build with signal node-type" ON "" OFF)
|
||||
|
|
|
@ -21,17 +21,40 @@
|
|||
###################################################################################
|
||||
|
||||
find_path(OPAL_INCLUDE_DIR
|
||||
NAMES opal/AsyncApi.h
|
||||
NAMES AsyncApi.h
|
||||
HINTS
|
||||
/usr/opalrt/common/include_target/
|
||||
)
|
||||
|
||||
find_library(OPAL_LIBRARY
|
||||
find_library(OPAL_LIBRARY_ASYNCAPICORE
|
||||
NAMES OpalAsyncApiCore
|
||||
HINTS
|
||||
/usr/opalrt/common/lib/
|
||||
)
|
||||
|
||||
find_library(OPAL_LIBRARY_IRC
|
||||
NAMES irc
|
||||
HINTS
|
||||
/usr/opalrt/common/lib/
|
||||
)
|
||||
|
||||
find_library(OPAL_LIBRARY_OPAL_UTILS
|
||||
NAMES OpalUtils
|
||||
HINTS
|
||||
/usr/opalrt/common/lib/redhawk
|
||||
)
|
||||
|
||||
find_library(OPAL_LIBRARY_OPAL_CORE
|
||||
NAMES OpalCore
|
||||
HINTS
|
||||
/usr/opalrt/common/lib/redhawk
|
||||
)
|
||||
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Opal DEFAULT_MSG OPAL_LIBRARY OPAL_INCLUDE_DIR)
|
||||
|
||||
mark_as_advanced(OPAL_INCLUDE_DIR OPAL_LIBRARY)
|
||||
|
||||
set(OPAL_LIBRARIES ${OPAL_LIBRARY} OpalCore OpalUtils irc)
|
||||
set(OPAL_LIBRARIES ${OPAL_LIBRARY} ${OPAL_LIBRARY_OPALUTILS} ${OPAL_LIBRARY_OPALCORE} ${OPAL_LIBRARY_IRC} $ENV{OPAL_LIBPATH} $ENV{OPAL_LIBS})
|
||||
set(OPAL_INCLUDE_DIRS ${OPAL_INCLUDE_DIR})
|
||||
|
|
73
include/villas/log_opal_sink.hpp
Normal file
73
include/villas/log_opal_sink.hpp
Normal file
|
@ -0,0 +1,73 @@
|
|||
/** Log sink for OPAL-RTs OpalPrint().
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLAScommon
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <villas/log.hpp>
|
||||
#include <villas/config.h>
|
||||
|
||||
#include <spdlog/sinks/base_sink.h>
|
||||
#include <spdlog/details/null_mutex.h>
|
||||
|
||||
extern "C" {
|
||||
/* Define RTLAB before including OpalPrint.h for messages to be sent
|
||||
* to the OpalDisplay. Otherwise stdout will be used. */
|
||||
#define RTLAB
|
||||
#include <OpalPrint.h>
|
||||
}
|
||||
|
||||
namespace villas {
|
||||
namespace node {
|
||||
|
||||
template<typename Mutex>
|
||||
class OpalSink : public spdlog::sinks::base_sink<Mutex>
|
||||
{
|
||||
|
||||
protected:
|
||||
void sink_it_(const spdlog::details::log_msg &msg) override
|
||||
{
|
||||
#ifdef WITH_NODE_OPAL
|
||||
fmt::memory_buffer formatted;
|
||||
|
||||
sink::formatter_->format(msg, formatted);
|
||||
|
||||
auto str = fmt::to_string(formatted).c_str();
|
||||
|
||||
OpalPrint(PROJECT_NAME ": %s\n", str);
|
||||
#endif
|
||||
}
|
||||
|
||||
void flush_() override
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
};
|
||||
|
||||
using OpalSink_mt = OpalSink<std::mutex>;
|
||||
using OpalSink_st = OpalSink<spdlog::details::null_mutex>;
|
||||
|
||||
|
||||
} /* namespace node */
|
||||
} /* namespace villas */
|
|
@ -51,6 +51,7 @@
|
|||
/* Available Features */
|
||||
#cmakedefine WITH_WEB
|
||||
#cmakedefine WITH_NODE_WEBSOCKET
|
||||
#cmakedefine WITH_NODE_OPAL
|
||||
#cmakedefine WITH_API
|
||||
#cmakedefine WITH_HOOKS
|
||||
#cmakedefine WITH_CONFIG
|
||||
|
|
|
@ -32,24 +32,22 @@
|
|||
#include <pthread.h>
|
||||
|
||||
#include <villas/node.h>
|
||||
#include <villas/msg.h>
|
||||
#include <villas/sample.h>
|
||||
|
||||
/* Define RTLAB before including OpalPrint.h for messages to be sent
|
||||
* to the OpalDisplay. Otherwise stdout will be used. */
|
||||
#define RTLAB
|
||||
#include "OpalPrint.h"
|
||||
#include "AsyncApi.h"
|
||||
#include "OpalGenAsyncParamCtrl.h"
|
||||
extern "C" {
|
||||
#include <OpalGenAsyncParamCtrl.h>
|
||||
}
|
||||
|
||||
struct opal {
|
||||
int reply;
|
||||
int mode;
|
||||
int sequenceNo;
|
||||
|
||||
int send_id;
|
||||
int recv_id;
|
||||
unsigned sendID;
|
||||
unsigned recvID;
|
||||
|
||||
Opal_SendAsyncParam send_params;
|
||||
Opal_RecvAsyncParam recv_params;
|
||||
Opal_SendAsyncParam sendParams;
|
||||
Opal_RecvAsyncParam recvParams;
|
||||
};
|
||||
|
||||
/** Initialize global OPAL settings and maps shared memory regions.
|
||||
|
@ -58,6 +56,8 @@ struct opal {
|
|||
*/
|
||||
int opal_type_start(villas::node::SuperNode *sn);
|
||||
|
||||
int opal_register_region(int argc, char *argv[]);
|
||||
|
||||
/** Free global OPAL settings and unmaps shared memory regions.
|
||||
*
|
||||
* @see node_type::type_stop
|
||||
|
|
|
@ -22,35 +22,91 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
#include <villas/nodes/opal.hpp>
|
||||
#include <villas/utils.hpp>
|
||||
#include <villas/plugin.h>
|
||||
#include <villas/exceptions.hpp>
|
||||
|
||||
extern "C" {
|
||||
/* Define RTLAB before including OpalPrint.h for messages to be sent
|
||||
* to the OpalDisplay. Otherwise stdout will be used. */
|
||||
#define RTLAB
|
||||
#include <OpalPrint.h>
|
||||
#include <AsyncApi.h>
|
||||
#include <OpalGenAsyncParamCtrl.h>
|
||||
}
|
||||
|
||||
|
||||
/* Private static storage */
|
||||
static char *async_shmem_name; /**< Shared Memory identifiers and size, provided via argv. */
|
||||
static char *print_shmem_name; /**< Shared Memory identifiers and size, provided via argv. */
|
||||
static int async_shmem_size; /**< Shared Memory identifiers and size, provided via argv. */
|
||||
static std::string asyncShmemName; /**< Shared Memory identifiers and size, provided via argv. */
|
||||
static std::string printShmemName; /**< Shared Memory identifiers and size, provided via argv. */
|
||||
static size_t asyncShmemSize; /**< Shared Memory identifiers and size, provided via argv. */
|
||||
|
||||
static int send_icons, recv_icons; /** Number of send blocks used in the running OPAL model. */
|
||||
static int *send_ids, *recv_ids; /** A dynamically allocated array of SendIDs. */
|
||||
static std::vector<unsigned> sendIDs, recvIDs; /** A dynamically allocated array of SendIDs. */
|
||||
|
||||
static Opal_GenAsyncParam_Ctrl params; /** String and Float parameters, provided by the OPAL AsyncProcess block. */
|
||||
static Opal_GenAsyncParam_Ctrl params; /** String and Float parameters, provided by the OPAL AsyncProcess block. */
|
||||
|
||||
static pthread_mutex_t lock; /** Big Global Lock for libOpalAsync API */
|
||||
static pthread_mutex_t lock; /** Big Global Lock for libOpalAsync API */
|
||||
|
||||
using namespace villas;
|
||||
using namespace villas::utils;
|
||||
|
||||
extern "C" {
|
||||
int __xstat(int ver, const char * path, struct stat * stat_buf)
|
||||
{
|
||||
return stat(path, stat_buf);
|
||||
}
|
||||
|
||||
int backtrace(void **buffer, int size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char **backtrace_symbols(void *const *buffer, int size)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void backtrace_symbols_fd(void *const *buffer, int size, int fd)
|
||||
{
|
||||
}
|
||||
|
||||
void * _intel_fast_memset(void *b, int c, size_t len)
|
||||
{
|
||||
return memset(b, c, len);
|
||||
}
|
||||
|
||||
void * _intel_fast_memcpy(void *dst, const void *src, size_t n)
|
||||
{
|
||||
return memcpy(dst, src, n);
|
||||
}
|
||||
|
||||
int _intel_fast_memcmp(const void *s1, const void *s2, size_t n)
|
||||
{
|
||||
return memcmp(s1, s2, n);
|
||||
}
|
||||
}
|
||||
|
||||
int opal_register_region(int argc, char *argv[])
|
||||
{
|
||||
async_shmem_name = argv[1];
|
||||
async_shmem_size = atoi(argv[2]);
|
||||
print_shmem_name = argv[3];
|
||||
asyncShmemName = argv[1];
|
||||
asyncShmemSize = atoi(argv[2]);
|
||||
printShmemName = argv[3];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int opal_type_start(villas::node::SuperNode *sn)
|
||||
{
|
||||
int err;
|
||||
int err, noRecvIcons, noSendIcons;
|
||||
|
||||
/* @todo: Port to C++
|
||||
if (sn->cli.argc != 4)
|
||||
|
@ -59,12 +115,12 @@ int opal_type_start(villas::node::SuperNode *sn)
|
|||
pthread_mutex_init(&lock, nullptr);
|
||||
|
||||
/* Enable the OpalPrint function. This prints to the OpalDisplay. */
|
||||
err = OpalSystemCtrl_Register(print_shmem_name);
|
||||
err = OpalSystemCtrl_Register((char *) printShmemName.c_str());
|
||||
if (err != EOK)
|
||||
error("OpalPrint() access not available (%d)", err);
|
||||
|
||||
/* Open Share Memory created by the model. */
|
||||
err = OpalOpenAsyncMem(async_shmem_size, async_shmem_name);
|
||||
err = OpalOpenAsyncMem(asyncShmemSize, asyncShmemName.c_str());
|
||||
if (err != EOK)
|
||||
error("Model shared memory not available (%d)", err);
|
||||
|
||||
|
@ -73,23 +129,21 @@ int opal_type_start(villas::node::SuperNode *sn)
|
|||
error("Could not get OPAL controller parameters (%d)", err);
|
||||
|
||||
/* Get list of Send and RecvIDs */
|
||||
err = OpalGetNbAsyncSendIcon(&send_icons);
|
||||
err = OpalGetNbAsyncSendIcon(&noSendIcons);
|
||||
if (err != EOK)
|
||||
error("Failed to get number of send blocks (%d)", err);
|
||||
err = OpalGetNbAsyncRecvIcon(&recv_icons);
|
||||
err = OpalGetNbAsyncRecvIcon(&noRecvIcons);
|
||||
if (err != EOK)
|
||||
error("Failed to get number of recv blocks (%d)", err);
|
||||
|
||||
send_ids = new int[send_icons];
|
||||
recv_ids = new int[recv_icons];
|
||||
sendIDs.resize(noSendIcons);
|
||||
recvIDs.resize(noRecvIcons);
|
||||
|
||||
if (!send_ids || !recv_ids)
|
||||
throw MemoryAllocationError();
|
||||
|
||||
err = OpalGetAsyncSendIDList(send_ids, send_icons * sizeof(int));
|
||||
err = OpalGetAsyncSendIDList(sendIDs.data(), noSendIcons * sizeof(int));
|
||||
if (err != EOK)
|
||||
error("Failed to get list of send ids (%d)", err);
|
||||
err = OpalGetAsyncRecvIDList(recv_ids, recv_icons * sizeof(int));
|
||||
|
||||
err = OpalGetAsyncRecvIDList(recvIDs.data(), noRecvIcons * sizeof(int));
|
||||
if (err != EOK)
|
||||
error("Failed to get list of recv ids (%d)", err);
|
||||
|
||||
|
@ -106,21 +160,18 @@ int opal_type_stop()
|
|||
{
|
||||
int err;
|
||||
|
||||
err = OpalCloseAsyncMem(async_shmem_size, async_shmem_name);
|
||||
err = OpalCloseAsyncMem(asyncShmemSize, asyncShmemName.c_str());
|
||||
if (err != EOK)
|
||||
error("Failed to close shared memory area (%d)", err);
|
||||
|
||||
debug(LOG_OPAL | 4, "Closing OPAL shared memory mapping");
|
||||
|
||||
err = OpalSystemCtrl_UnRegister(print_shmem_name);
|
||||
err = OpalSystemCtrl_UnRegister((char *) printShmemName.c_str());
|
||||
if (err != EOK)
|
||||
error("Failed to close shared memory for system control (%d)", err);
|
||||
|
||||
pthread_mutex_destroy(&lock);
|
||||
|
||||
delete[] send_ids;
|
||||
delete[] recv_ids;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -128,26 +179,21 @@ int opal_print_global()
|
|||
{
|
||||
debug(LOG_OPAL | 2, "Controller ID: %u", params.controllerID);
|
||||
|
||||
auto *sbuf = new (std::nothrow) char[send_icons * 5];
|
||||
auto *rbuf = new (std::nothrow) char[recv_icons * 5];
|
||||
std::stringstream sss, rss;
|
||||
|
||||
if (!sbuf || !rbuf)
|
||||
throw MemoryAllocationError();
|
||||
for (auto i : sendIDs)
|
||||
sss << i << " ";
|
||||
for (auto i : recvIDs)
|
||||
rss << i << " ";
|
||||
|
||||
for (int i = 0; i < send_icons; i++)
|
||||
strcatf(&sbuf, "%u ", send_ids[i]);
|
||||
for (int i = 0; i < recv_icons; i++)
|
||||
strcatf(&rbuf, "%u ", recv_ids[i]);
|
||||
|
||||
debug(LOG_OPAL | 2, "Send Blocks: %s", sbuf);
|
||||
debug(LOG_OPAL | 2, "Receive Blocks: %s", rbuf);
|
||||
|
||||
delete[] sbuf;
|
||||
delete[] rbuf;
|
||||
debug(LOG_OPAL | 2, "Send Blocks: %s", sss.str().c_str());
|
||||
debug(LOG_OPAL | 2, "Receive Blocks: %s", rss.str().c_str());
|
||||
|
||||
debug(LOG_OPAL | 2, "Control Block Parameters:");
|
||||
|
||||
for (int i = 0; i < GENASYNC_NB_FLOAT_PARAM; i++)
|
||||
debug(LOG_OPAL | 2, "FloatParam[]%u] = %f", i, params.FloatParam[i]);
|
||||
|
||||
for (int i = 0; i < GENASYNC_NB_STRING_PARAM; i++)
|
||||
debug(LOG_OPAL | 2, "StringParam[%u] = %s", i, params.StringParam[i]);
|
||||
|
||||
|
@ -162,8 +208,8 @@ int opal_parse(struct vnode *n, json_t *cfg)
|
|||
json_error_t err;
|
||||
|
||||
ret = json_unpack_ex(cfg, &err, 0, "{ s: i, s: i, s: b }",
|
||||
"send_id", &o->send_id,
|
||||
"recv_id", &o->recv_id,
|
||||
"sendID", &o->sendID,
|
||||
"recvID", &o->recvID,
|
||||
"reply", &o->reply
|
||||
);
|
||||
if (ret)
|
||||
|
@ -178,8 +224,8 @@ char * opal_print(struct vnode *n)
|
|||
|
||||
/** @todo: Print send_params, recv_params */
|
||||
|
||||
return strf("send_id=%u, recv_id=%u, reply=%u",
|
||||
o->send_id, o->recv_id, o->reply);
|
||||
return strf("sendID=%u, recvID=%u, reply=%u",
|
||||
o->sendID, o->recvID, o->reply);
|
||||
}
|
||||
|
||||
int opal_start(struct vnode *n)
|
||||
|
@ -188,39 +234,36 @@ int opal_start(struct vnode *n)
|
|||
|
||||
/* Search for valid send and recv ids */
|
||||
int sfound = 0, rfound = 0;
|
||||
for (int i = 0; i < send_icons; i++)
|
||||
sfound += send_ids[i] == o->send_id;
|
||||
for (int i = 0; i < send_icons; i++)
|
||||
rfound += send_ids[i] == o->send_id;
|
||||
for (auto i : sendIDs)
|
||||
sfound += i == o->sendID;
|
||||
for (auto i : recvIDs)
|
||||
rfound += i == o->sendID;
|
||||
|
||||
if (!sfound)
|
||||
error("Invalid send_id '%u' for node %s", o->send_id, node_name(n));
|
||||
error("Invalid sendID '%u' for node %s", o->sendID, node_name(n));
|
||||
if (!rfound)
|
||||
error("Invalid recv_id '%u' for node %s", o->recv_id, node_name(n));
|
||||
error("Invalid recvID '%u' for node %s", o->recvID, node_name(n));
|
||||
|
||||
/* Get some more informations and paramters from OPAL-RT */
|
||||
OpalGetAsyncSendIconMode(&o->mode, o->send_id);
|
||||
OpalGetAsyncSendParameters(&o->send_params, sizeof(Opal_SendAsyncParam), o->send_id);
|
||||
OpalGetAsyncRecvParameters(&o->recv_params, sizeof(Opal_RecvAsyncParam), o->recv_id);
|
||||
OpalGetAsyncSendIconMode(&o->mode, o->sendID);
|
||||
OpalGetAsyncSendParameters(&o->sendParams, sizeof(Opal_SendAsyncParam), o->sendID);
|
||||
OpalGetAsyncRecvParameters(&o->recvParams, sizeof(Opal_RecvAsyncParam), o->recvID);
|
||||
|
||||
o->sequenceNo = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int opal_stop(struct vnode *n)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int opal_read(struct vnode *n, struct pool *pool, unsigned cnt)
|
||||
int opal_read(struct vnode *n, struct sample *smps[], unsigned cnt, unsigned *release)
|
||||
{
|
||||
struct opal *o = (struct opal *) n->_vd;
|
||||
|
||||
int state, len, ret;
|
||||
int state, ret, len;
|
||||
unsigned id;
|
||||
|
||||
struct msg *m = &pool[first % poolsize];
|
||||
struct sample *s = smps[0];
|
||||
|
||||
double data[MSG_VALUES];
|
||||
double data[s->capacity];
|
||||
|
||||
if (cnt != 1)
|
||||
error("The OPAL-RT node type does not support combining!");
|
||||
|
@ -230,33 +273,33 @@ int opal_read(struct vnode *n, struct pool *pool, unsigned cnt)
|
|||
ret = OpalWaitForAsyncSendRequest(&id);
|
||||
if (ret != EOK) {
|
||||
state = OpalGetAsyncModelState();
|
||||
if ((state == State::RESET) || (state == State::STOP))
|
||||
if ((state == STATE_RESET) || (state == STATE_STOP))
|
||||
error("OpalGetAsyncModelState(): Model stopped or resetted!");
|
||||
|
||||
return -1; /* @todo correct return value */
|
||||
}
|
||||
} while (id != o->send_id);
|
||||
} while (id != o->sendID);
|
||||
|
||||
/* No errors encountered yet */
|
||||
OpalSetAsyncSendIconError(0, o->send_id);
|
||||
OpalSetAsyncSendIconError(0, o->sendID);
|
||||
|
||||
/* Get the size of the data being sent by the unblocking SendID */
|
||||
OpalGetAsyncSendIconDataLength(&len, o->send_id);
|
||||
if (len > sizeof(data)) {
|
||||
warning("Ignoring the last %u of %u values for OPAL node %s (send_id=%u).",
|
||||
len / sizeof(double) - MSG_VALUES, len / sizeof(double), node_name(n), o->send_id);
|
||||
OpalGetAsyncSendIconDataLength(&len, o->sendID);
|
||||
if ((unsigned) len > s->capacity * sizeof(s->data[0])) {
|
||||
warning("Ignoring the last %u of %u values for OPAL node %s (sendID=%u).",
|
||||
len / sizeof(double) - s->capacity, len / sizeof(double), node_name(n), o->sendID);
|
||||
|
||||
len = sizeof(data);
|
||||
}
|
||||
|
||||
/* Read data from the model */
|
||||
OpalGetAsyncSendIconData(data, len, o->send_id);
|
||||
OpalGetAsyncSendIconData(data, len, o->sendID);
|
||||
|
||||
m->sequence = htons(o->seq_no++);
|
||||
m->length = len / sizeof(double);
|
||||
s->sequence = htons(o->sequenceNo++);
|
||||
s->length = (unsigned) len / sizeof(double);
|
||||
|
||||
for (int i = 0; i < m->length; i++)
|
||||
m->data[i].f = (float) data[i]; /* OPAL provides double precission */
|
||||
for (unsigned i = 0; i < s->length; i++)
|
||||
s->data[i].f = (float) data[i]; /* OPAL provides double precission */
|
||||
|
||||
/* This next call allows the execution of the "asynchronous" process
|
||||
* to actually be synchronous with the model. To achieve this, you
|
||||
|
@ -265,46 +308,46 @@ int opal_read(struct vnode *n, struct pool *pool, unsigned cnt)
|
|||
* the model to wait for this process to call this
|
||||
* OpalAsyncSendRequestDone function before continuing. */
|
||||
if (o->reply)
|
||||
OpalAsyncSendRequestDone(o->send_id);
|
||||
OpalAsyncSendRequestDone(o->sendID);
|
||||
|
||||
/* Before continuing, we make sure that the real-time model
|
||||
* has not been stopped. If it has, we quit. */
|
||||
state = OpalGetAsyncModelState();
|
||||
if ((state == State::RESET) || (state == State::STOP))
|
||||
if ((state == STATE_RESET) || (state == STATE_STOP))
|
||||
error("OpalGetAsyncModelState(): Model stopped or resetted!");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int opal_write(struct vnode *n, struct pool *pool, unsigned cnt)
|
||||
int opal_write(struct vnode *n, struct sample *smps[], unsigned cnt, unsigned *release)
|
||||
{
|
||||
struct opal *o = (struct opal *) n->_vd;
|
||||
|
||||
struct msg *m = &pool[first % poolsize];
|
||||
struct sample *s = smps[0];
|
||||
|
||||
int state;
|
||||
int len;
|
||||
double data[m->length];
|
||||
double data[s->length];
|
||||
|
||||
if (cnt != 1)
|
||||
error("The OPAL-RT node type does not support combining!");
|
||||
|
||||
state = OpalGetAsyncModelState();
|
||||
if ((state == State::RESET) || (state == State::STOP))
|
||||
if ((state == STATE_RESET) || (state == STATE_STOP))
|
||||
error("OpalGetAsyncModelState(): Model stopped or resetted!");
|
||||
|
||||
OpalSetAsyncRecvIconStatus(m->sequence, o->recv_id); /* Set the Status to the message ID */
|
||||
OpalSetAsyncRecvIconError(0, o->recv_id); /* Set the Error to 0 */
|
||||
OpalSetAsyncRecvIconStatus(s->sequence, o->recvID); /* Set the Status to the message ID */
|
||||
OpalSetAsyncRecvIconError(0, o->recvID); /* Set the Error to 0 */
|
||||
|
||||
/* Get the number of signals to send back to the model */
|
||||
OpalGetAsyncRecvIconDataLength(&len, o->recv_id);
|
||||
if (len > sizeof(data))
|
||||
warning("Node %s is expecting more signals (%u) than values in message (%u)", node_name(n), len / sizeof(double), m->length);
|
||||
OpalGetAsyncRecvIconDataLength(&len, o->recvID);
|
||||
if ((unsigned) len > sizeof(data))
|
||||
warning("Node %s is expecting more signals (%u) than values in message (%u)", node_name(n), len / sizeof(double), s->length);
|
||||
|
||||
for (int i = 0; i < m->length; i++)
|
||||
data[i] = (double) m->data[i].f; /* OPAL expects double precission */
|
||||
for (unsigned i = 0; i < s->length; i++)
|
||||
data[i] = (double) s->data[i].f; /* OPAL expects double precission */
|
||||
|
||||
OpalSetAsyncRecvIconData(data, m->length * sizeof(double), o->recv_id);
|
||||
OpalSetAsyncRecvIconData(data, s->length * sizeof(double), o->recvID);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -317,14 +360,13 @@ static void register_plugin() {
|
|||
p.description = "run as OPAL Asynchronous Process (libOpalAsyncApi)";
|
||||
p.type = PluginType::NODE;
|
||||
p.node.instances.state = State::DESTROYED;
|
||||
p.node.vectoroize = 1;
|
||||
p.node.vectorize = 1;
|
||||
p.node.size = sizeof(struct opal);
|
||||
p.node.type.start = opal_type_start;
|
||||
p.node.type.stop = opal_type_stop;
|
||||
p.node.parse = opal_parse;
|
||||
p.node.print = opal_print;
|
||||
p.node.start = opal_start;
|
||||
p.node.stop = opal_stop;
|
||||
p.node.read = opal_read;
|
||||
p.node.write = opal_write;
|
||||
|
||||
|
|
|
@ -51,6 +51,11 @@ target_link_libraries(villas-pipe PUBLIC villas Threads::Threads)
|
|||
add_executable(villas-signal villas-signal.cpp)
|
||||
target_link_libraries(villas-signal PUBLIC villas)
|
||||
|
||||
if(WITH_NODE_OPAL)
|
||||
target_include_directories(villas-node PRIVATE ${OPAL_INCLUDE_DIRS})
|
||||
target_link_libraries(villas-node PRIVATE ${OPAL_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(WITH_GRAPHVIZ)
|
||||
add_executable(villas-graph villas-graph.cpp)
|
||||
target_link_libraries(villas-graph PUBLIC villas)
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
#include <villas/kernel/kernel.hpp>
|
||||
#include <villas/kernel/rt.hpp>
|
||||
|
||||
#ifdef ENABLE_OPAL_ASYNC
|
||||
#ifdef WITH_NODE_OPAL
|
||||
#include <villas/nodes/opal.hpp>
|
||||
#endif
|
||||
|
||||
|
@ -95,11 +95,11 @@ protected:
|
|||
<< " CONFIG is the path to an optional configuration file" << std::endl
|
||||
<< " if omitted, VILLASnode will start without a configuration" << std::endl
|
||||
<< " and wait for provisioning over the web interface." << std::endl << std::endl
|
||||
#ifdef ENABLE_OPAL_ASYNC
|
||||
#ifdef WITH_NODE_OPAL
|
||||
<< "Usage: villas-node OPAL_ASYNC_SHMEM_NAME OPAL_ASYNC_SHMEM_SIZE OPAL_PRINT_SHMEM_NAME" << std::endl
|
||||
<< " This type of invocation is used by OPAL-RT Asynchronous processes." << std::endl
|
||||
<< " See in the RT-LAB User Guide for more information." << std::endl << std::endl
|
||||
#endif /* ENABLE_OPAL_ASYNC */
|
||||
#endif /* WITH_NODE_OPAL */
|
||||
|
||||
<< "Supported node-types:" << std::endl;
|
||||
plugin_dump(PluginType::NODE);
|
||||
|
@ -128,8 +128,8 @@ protected:
|
|||
|
||||
void parse()
|
||||
{
|
||||
/* Check arguments */
|
||||
#ifdef ENABLE_OPAL_ASYNC
|
||||
/* Check arguments */
|
||||
#ifdef WITH_NODE_OPAL
|
||||
if (argc != 4) {
|
||||
usage();
|
||||
exit(EXIT_FAILURE);
|
||||
|
@ -137,7 +137,7 @@ protected:
|
|||
|
||||
opal_register_region(argc, argv);
|
||||
|
||||
uri = "opal-shmem.conf";
|
||||
uri = "villas-node.conf";
|
||||
#else
|
||||
|
||||
/* Parse optional command line arguments */
|
||||
|
@ -172,13 +172,6 @@ protected:
|
|||
|
||||
int main()
|
||||
{
|
||||
#ifdef __linux__
|
||||
/* Checks system requirements*/
|
||||
auto required = utils::Version(KERNEL_VERSION_MAJ, KERNEL_VERSION_MIN);
|
||||
if (kernel::getVersion() < required)
|
||||
throw RuntimeError("Your kernel version is to old: required >= {}.{}", KERNEL_VERSION_MAJ, KERNEL_VERSION_MIN);
|
||||
#endif /* __linux__ */
|
||||
|
||||
if (!uri.empty())
|
||||
sn.parse(uri);
|
||||
else
|
||||
|
|
Loading…
Add table
Reference in a new issue