2016-06-19 19:23:19 +02:00
|
|
|
/** Node type: Wrapper around RSCAD CBuilder model
|
|
|
|
*
|
|
|
|
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
2017-03-03 20:20:13 -04:00
|
|
|
* @copyright 2017, Steffen Vogel
|
2016-06-19 19:23:19 +02:00
|
|
|
**********************************************************************************/
|
|
|
|
|
2017-08-30 13:30:31 +02:00
|
|
|
#include <sys/eventfd.h>
|
|
|
|
|
2016-06-19 19:23:19 +02:00
|
|
|
#include "node.h"
|
2016-06-26 15:28:34 +02:00
|
|
|
#include "log.h"
|
2017-02-12 14:35:05 -03:00
|
|
|
#include "plugin.h"
|
2017-03-11 23:50:30 -03:00
|
|
|
#include "utils.h"
|
2017-02-12 14:35:05 -03:00
|
|
|
|
2016-06-26 15:28:34 +02:00
|
|
|
#include "nodes/cbuilder.h"
|
|
|
|
|
2017-08-03 00:19:27 +02:00
|
|
|
int cbuilder_parse(struct node *n, json_t *cfg)
|
2016-06-26 15:28:34 +02:00
|
|
|
{
|
|
|
|
struct cbuilder *cb = n->_vd;
|
2017-08-03 00:19:27 +02:00
|
|
|
json_t *cfg_param, *cfg_params = NULL;
|
2016-06-26 15:28:34 +02:00
|
|
|
|
|
|
|
const char *model;
|
|
|
|
|
2017-08-03 00:19:27 +02:00
|
|
|
int ret;
|
|
|
|
size_t index;
|
|
|
|
json_error_t err;
|
|
|
|
|
2017-09-04 23:16:58 +02:00
|
|
|
ret = json_unpack_ex(cfg, &err, 0, "{ s: F, s: s, s: b }",
|
2017-08-03 00:19:27 +02:00
|
|
|
"timestep", &cb->timestep,
|
|
|
|
"model", &model,
|
|
|
|
"parameters", &cfg_params
|
|
|
|
);
|
|
|
|
if (ret)
|
|
|
|
jerror(&err, "Failed to parse configuration of node %s", node_name(n));
|
2017-05-05 19:24:16 +00:00
|
|
|
|
2017-02-18 10:51:43 -05:00
|
|
|
cb->model = (struct cbuilder_model *) plugin_lookup(PLUGIN_TYPE_MODEL_CBUILDER, model);
|
2016-06-26 15:28:34 +02:00
|
|
|
if (!cb->model)
|
2017-08-03 00:19:27 +02:00
|
|
|
error("Unknown model '%s' of node %s", model, node_name(n));
|
2017-05-05 19:24:16 +00:00
|
|
|
|
2016-06-26 15:28:34 +02:00
|
|
|
if (cfg_params) {
|
2017-08-03 00:19:27 +02:00
|
|
|
if (!json_is_array(cfg_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-08-03 00:19:27 +02:00
|
|
|
cb->paramlen = json_array_size(cfg_params);
|
2016-06-26 15:28:34 +02:00
|
|
|
cb->params = alloc(cb->paramlen * sizeof(double));
|
2017-05-05 19:24:16 +00:00
|
|
|
|
2017-08-03 00:19:27 +02:00
|
|
|
json_array_foreach(cfg_params, index, cfg_param) {
|
|
|
|
if (json_is_number(cfg_param))
|
|
|
|
error("Setting 'parameters' of node %s must be an JSON array of numbers!", node_name(n));
|
|
|
|
|
|
|
|
cb->params[index] = json_number_value(cfg_params);
|
|
|
|
|
|
|
|
}
|
2016-06-26 15:28:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2016-06-19 19:23:19 +02:00
|
|
|
}
|
|
|
|
|
2017-03-11 23:30:24 -03: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;
|
|
|
|
struct cbuilder *cb = n->_vd;
|
|
|
|
|
|
|
|
/* Initialize mutex and cv */
|
|
|
|
pthread_mutex_init(&cb->mtx, NULL);
|
2017-09-04 23:16:58 +02:00
|
|
|
|
2017-08-30 13:30:31 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-03-11 23:30:24 -03:00
|
|
|
int cbuilder_stop(struct node *n)
|
2016-06-26 15:28:34 +02:00
|
|
|
{
|
2017-08-30 13:30:31 +02:00
|
|
|
int ret;
|
2016-06-26 15:28:34 +02:00
|
|
|
struct cbuilder *cb = n->_vd;
|
2017-09-04 23:16:58 +02:00
|
|
|
|
2017-08-30 13:30:31 +02:00
|
|
|
ret = close(cb->eventfd);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
2017-05-05 19:24:16 +00:00
|
|
|
|
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)
|
|
|
|
{
|
2016-06-26 15:28:34 +02:00
|
|
|
struct cbuilder *cb = n->_vd;
|
2016-06-19 19:23:19 +02:00
|
|
|
struct sample *smp = smps[0];
|
2017-09-04 23:16:58 +02:00
|
|
|
|
2017-08-30 13:30:31 +02:00
|
|
|
uint64_t cntr;
|
2017-09-04 23:16:58 +02:00
|
|
|
|
2017-08-30 13:30:31 +02:00
|
|
|
read(cb->eventfd, &cntr, sizeof(cntr));
|
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);
|
2017-09-04 23:16:58 +02:00
|
|
|
|
2017-08-14 14:42:07 +02:00
|
|
|
float data[smp->capacity];
|
2016-06-26 15:28:34 +02:00
|
|
|
|
2017-08-14 14:42:07 +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];
|
2017-09-04 23:16:58 +02:00
|
|
|
|
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)
|
|
|
|
{
|
2016-06-26 15:28:34 +02:00
|
|
|
struct cbuilder *cb = n->_vd;
|
2016-06-19 19:23:19 +02:00
|
|
|
struct sample *smp = smps[0];
|
2017-05-05 19:24:16 +00:00
|
|
|
|
2016-06-26 15:28:34 +02:00
|
|
|
pthread_mutex_lock(&cb->mtx);
|
2017-09-04 23:16:58 +02:00
|
|
|
|
2017-08-14 14:42:07 +02:00
|
|
|
float flt = smp->data[0].f;
|
2016-06-26 15:28:34 +02:00
|
|
|
|
2017-08-14 14:42:07 +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++;
|
2017-09-04 23:16:58 +02:00
|
|
|
|
2017-08-30 13:30:31 +02:00
|
|
|
uint64_t incr = 1;
|
|
|
|
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
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-08-30 13:30:31 +02:00
|
|
|
int cbuilder_fd(struct node *n)
|
|
|
|
{
|
|
|
|
struct cbuilder *cb = n->_vd;
|
2017-09-04 23:16:58 +02:00
|
|
|
|
2017-08-30 13:30:31 +02:00
|
|
|
return cb->eventfd;
|
|
|
|
}
|
|
|
|
|
2017-02-12 14:35:05 -03:00
|
|
|
static struct plugin p = {
|
2016-06-19 19:23:19 +02:00
|
|
|
.name = "cbuilder",
|
|
|
|
.description = "RTDS CBuilder model",
|
2017-02-12 14:35:05 -03:00
|
|
|
.type = PLUGIN_TYPE_NODE,
|
|
|
|
.node = {
|
|
|
|
.vectorize = 1,
|
|
|
|
.size = sizeof(struct cbuilder),
|
|
|
|
.parse = cbuilder_parse,
|
2017-03-11 23:30:24 -03:00
|
|
|
.start = cbuilder_start,
|
|
|
|
.stop = cbuilder_stop,
|
2017-02-12 14:35:05 -03:00
|
|
|
.read = cbuilder_read,
|
2017-08-30 13:30:31 +02:00
|
|
|
.write = cbuilder_write,
|
|
|
|
.fd = cbuilder_fd
|
2017-02-12 14:35:05 -03:00
|
|
|
}
|
2016-06-19 19:23:19 +02:00
|
|
|
};
|
|
|
|
|
2017-02-12 14:35:05 -03:00
|
|
|
REGISTER_PLUGIN(&p)
|
2017-07-02 23:53:48 +02:00
|
|
|
LIST_INIT_STATIC(&p.node.instances)
|