1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-16 00:00:02 +01:00
VILLASnode/lib/nodes/cbuilder.c

184 lines
3.8 KiB
C
Raw Normal View History

2016-06-19 19:23:19 +02:00
/** Node type: Wrapper around RSCAD CBuilder model
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
2019-01-13 00:42:39 +01:00
* @copyright 2014-2019, Steffen Vogel
2016-06-19 19:23:19 +02:00
**********************************************************************************/
#include <sys/eventfd.h>
#include <villas/node.h>
#include <villas/log.h>
#include <villas/plugin.h>
#include <villas/utils.h>
#include <villas/nodes/cbuilder.h>
2016-06-26 15:28:34 +02:00
int cbuilder_parse(struct node *n, json_t *cfg)
2016-06-26 15:28:34 +02:00
{
2017-10-18 15:39:53 +02:00
struct cbuilder *cb = (struct cbuilder *) n->_vd;
2017-10-16 08:08:35 +02:00
json_t *json_param, *json_params = NULL;
2016-06-26 15:28:34 +02:00
const char *model;
int ret;
2018-08-07 18:40:32 +02:00
size_t i;
json_error_t err;
ret = json_unpack_ex(cfg, &err, 0, "{ s: F, s: s, s: b }",
"timestep", &cb->timestep,
"model", &model,
2017-10-16 08:08:35 +02:00
"parameters", &json_params
);
if (ret)
jerror(&err, "Failed to parse configuration of node %s", node_name(n));
cb->model = (struct cbuilder_model *) plugin_lookup(PLUGIN_TYPE_MODEL_CBUILDER, model);
2016-06-26 15:28:34 +02:00
if (!cb->model)
error("Unknown model '%s' of node %s", model, node_name(n));
2017-10-16 08:08:35 +02:00
if (json_params) {
if (!json_is_array(json_params))
error("Setting 'parameters' of node %s must be an JSON array of numbers!", node_name(n));
2016-06-26 15:28:34 +02:00
2017-10-16 08:08:35 +02:00
cb->paramlen = json_array_size(json_params);
2016-06-26 15:28:34 +02:00
cb->params = alloc(cb->paramlen * sizeof(double));
2018-08-07 18:40:32 +02:00
json_array_foreach(json_params, i, json_param) {
2017-10-16 08:08:35 +02:00
if (json_is_number(json_param))
error("Setting 'parameters' of node %s must be an JSON array of numbers!", node_name(n));
2018-08-07 18:40:32 +02:00
cb->params[i] = json_number_value(json_params);
}
2016-06-26 15:28:34 +02:00
}
return 0;
2016-06-19 19:23:19 +02:00
}
int cbuilder_start(struct node *n)
2016-06-19 19:23:19 +02:00
{
2016-06-26 15:28:34 +02:00
int ret;
2017-10-18 15:39:53 +02:00
struct cbuilder *cb = (struct cbuilder *) n->_vd;
2016-06-26 15:28:34 +02:00
/* Initialize mutex and cv */
pthread_mutex_init(&cb->mtx, NULL);
cb->eventfd = eventfd(0, 0);
if (cb->eventfd < 0)
return -1;
2016-06-26 15:28:34 +02:00
/* Currently only a single timestep per model / instance is supported */
cb->step = 0;
cb->read = 0;
ret = cb->model->init(cb);
if (ret)
error("Failed to intialize CBuilder model %s", node_name(n));
2016-06-19 19:23:19 +02:00
2016-06-26 15:28:34 +02:00
cb->model->ram();
2016-06-19 19:23:19 +02:00
2016-06-26 15:28:34 +02:00
return 0;
}
int cbuilder_stop(struct node *n)
2016-06-26 15:28:34 +02:00
{
int ret;
2017-10-18 15:39:53 +02:00
struct cbuilder *cb = (struct cbuilder *) n->_vd;
ret = close(cb->eventfd);
if (ret)
return ret;
2016-06-26 15:28:34 +02:00
pthread_mutex_destroy(&cb->mtx);
2016-06-19 19:23:19 +02:00
return 0;
}
int cbuilder_read(struct node *n, struct sample *smps[], unsigned cnt, unsigned *release)
2016-06-19 19:23:19 +02:00
{
2017-10-18 15:39:53 +02:00
struct cbuilder *cb = (struct cbuilder *) n->_vd;
2016-06-19 19:23:19 +02:00
struct sample *smp = smps[0];
uint64_t cntr;
ssize_t bytes;
bytes = read(cb->eventfd, &cntr, sizeof(cntr));
if (bytes != sizeof(cntr))
return -1;
2016-06-19 19:23:19 +02:00
2016-06-26 15:28:34 +02:00
/* Wait for completion of step */
pthread_mutex_lock(&cb->mtx);
float data[smp->capacity];
2016-06-26 15:28:34 +02:00
smp->length = cb->model->read(data, smp->capacity);
/* Cast float -> double */
for (int i = 0; i < smp->length; i++)
smp->data[i].f = data[i];
2016-06-26 15:28:34 +02:00
smp->sequence = cb->step;
cb->read = cb->step;
pthread_mutex_unlock(&cb->mtx);
2016-06-19 19:23:19 +02:00
return 1;
}
int cbuilder_write(struct node *n, struct sample *smps[], unsigned cnt, unsigned *release)
2016-06-19 19:23:19 +02:00
{
2017-10-18 15:39:53 +02:00
struct cbuilder *cb = (struct cbuilder *) n->_vd;
2016-06-19 19:23:19 +02:00
struct sample *smp = smps[0];
2016-06-26 15:28:34 +02:00
pthread_mutex_lock(&cb->mtx);
float flt = smp->data[0].f;
2016-06-26 15:28:34 +02:00
cb->model->write(&flt, smp->length);
2016-06-26 15:28:34 +02:00
cb->model->code();
2016-06-19 19:23:19 +02:00
2016-06-26 15:28:34 +02:00
cb->step++;
uint64_t incr = 1;
ssize_t bytes;
bytes = write(cb->eventfd, &incr, sizeof(incr));
2016-06-19 19:23:19 +02:00
2016-06-26 15:28:34 +02:00
pthread_mutex_unlock(&cb->mtx);
2016-06-19 19:23:19 +02:00
if (bytes != sizeof(incr))
return -1;
2016-06-19 19:23:19 +02:00
return 1;
}
int cbuilder_poll_fds(struct node *n, int fds[])
{
2017-10-18 15:39:53 +02:00
struct cbuilder *cb = (struct cbuilder *) n->_vd;
fds[0] = cb->eventfd;
return 1;
}
static struct plugin p = {
2016-06-19 19:23:19 +02:00
.name = "cbuilder",
.description = "RTDS CBuilder model",
.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,
.poll_fds = cbuilder_poll_fds
}
2016-06-19 19:23:19 +02:00
};
REGISTER_PLUGIN(&p)
2017-07-02 23:53:48 +02:00
LIST_INIT_STATIC(&p.node.instances)