Browse Source

Added support for nested module loading as a 'block'

When the blocks in the module use frequency 0.0 the module will
inherit the parent blocks frequency (typicall case for makin modules
of small networks which should just integrate with the parent network).
If a blocks segment in a module has any other frequency it will use that.

test_module.ctrl has been extended with module blocks, nested modules and
a module with its own frequency domain.
beaglebone
Jeroen Vreeken 7 years ago
parent
commit
41fb891434
16 changed files with 340 additions and 25 deletions
  1. +0
    -2
      controller/controller/controller_block.c
  2. +7
    -7
      controller/controller/controller_dumpdot.c
  3. +114
    -6
      controller/controller/controller_load.c
  4. +5
    -2
      controller/controller/controller_load_int.h
  5. +22
    -4
      controller/controller/controller_load_parser.y
  6. +70
    -2
      controller/controller/controller_module.c
  7. +5
    -0
      controller/controller/controller_module.h
  8. +6
    -0
      controller/controller/controller_time.c
  9. +1
    -0
      controller/controller/controller_time.h
  10. +1
    -0
      controller/test/build.mk
  11. +36
    -0
      controller/test/test_import.ctrl
  12. +4
    -0
      controller/test/test_import_gain1.ctrl
  13. +4
    -0
      controller/test/test_import_gain2.ctrl
  14. +32
    -2
      controller/test/test_module.ctrl
  15. +16
    -0
      controller/test/test_module_gg.ctrl
  16. +17
    -0
      controller/test/test_module_ggn.ctrl

+ 0
- 2
controller/controller/controller_block.c View File

@ -121,8 +121,6 @@ int controller_block_create(char *type, char *name, int argc, va_list ap)
ret = -1;
}
} else {
log_send(LOG_T_ERROR,
"Could not find create function or struct for block %s", type);
ret = -1;
}


+ 7
- 7
controller/controller/controller_dumpdot.c View File

@ -116,7 +116,7 @@ void controller_dumpdot(char *filename)
if (block->outputs > rows)
rows = block->outputs;
fprintf(fddot, "\t\t%s [label=<\n", block->name);
fprintf(fddot, "\t\t\"%s\" [label=<\n", block->name);
fprintf(fddot,
"\t\t\t<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">\n");
@ -152,7 +152,7 @@ void controller_dumpdot(char *filename)
for (j = 0; j < block->inputs; j++) {
if (block->input[j].ghostof) {
fprintf(fddot,
"\t\t%s:in_%s:e -> %s:in_%s:w [color=\"grey\"]\n",
"\t\t\"%s\":\"in_%s\":\"e\" -> \"%s\":\"in_%s\":\"w\" [color=\"grey\"]\n",
block->name, block->input[j].name,
block->input[j].ghostof->block->name,
block->input[j].ghostof->name);
@ -162,7 +162,7 @@ void controller_dumpdot(char *filename)
for (j = 0; j < block->outputs; j++) {
if (block->output[j].source != block) {
fprintf(fddot,
"\t\t%s:out_%s:e -> %s:out_%s:w [color=\"grey\"]\n",
"\t\t\"%s\":\"out_%s\":\"e\" -> \"%s\":\"out_%s\":\"w\" [color=\"grey\"]\n",
block->output[j].source->name,
block->output[j].sourceterm->name,
block->name, block->output[j].name);
@ -192,8 +192,8 @@ void controller_dumpdot(char *filename)
struct controller_block_link *link = controller_block_link_get(i);
fprintf(fddot,
"\t%s:out_%s:e -> "
"%s:in_%s:w "
"\t\"%s\":\"out_%s\":\"e\" -> "
"\"%s\":\"in_%s\":\"w\" "
"[%s, labeldistance=2.0, headlabel=<<i>(%s)</i>>, compound=true]\n",
link->outblock, link->outterm,
link->inblock, link->interm,
@ -208,7 +208,7 @@ void controller_dumpdot(char *filename)
fprintf(fddot,
"\ttrace_%s [shape=ellipse,label=\"%s\\n[%s]\",color=\"green\"];\n",
trace->name, trace->name, trace->unit);
fprintf(fddot, "\t%s:out_%s:e -> trace_%s [color=\"green\"]\n",
fprintf(fddot, "\t\"%s\":\"out_%s\":\"e\" -> \"trace_%s\" [color=\"green\"]\n",
trace->blockname, trace->termname, trace->name);
}
@ -227,7 +227,7 @@ void controller_dumpdot(char *filename)
bus = controller_bus_linked_bus(src, dst);
fprintf(fddot,
"\t%s:block_port:s -> %s:block_port:n "
"\t\"%s\":\"block_port\":\"s\" -> \"%s\":\"block_port\":\"n\" "
"[color=\"red\", "
"labeldistance=2.0, label=<%s <i>(%s)</i>>, "
"compound=true]\n",


+ 114
- 6
controller/controller/controller_load.c View File

@ -21,6 +21,9 @@
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <controller/controller_load_int.h>
#include <controller/controller_load_parser.tab.h>
@ -28,6 +31,7 @@
#include <controller/controller_load.h>
#include <controller/controller_sample.h>
#include <controller/controller_block.h>
#include <controller/controller_module.h>
#include <dynarg.h>
#include <limits.h>
@ -253,44 +257,126 @@ int controller_load_trigger(char *name, yyscan_t scanner)
return controller_sample_trigger(name, extra->va_list_argc, extra->va_list);
}
static char *rel2file(yyscan_t scanner, char *rel_name)
{
struct controller_load_extra *extra = yyget_extra(scanner);
struct stat stattmp;
char *ret;
char *tmp;
char *slash;
if (!stat(rel_name, &stattmp))
return strdup(rel_name);
if (!extra->filename)
return NULL;
tmp = strdup(extra->filename);
for (ret = tmp; *ret; ret++)
if (*ret == '/')
slash = ret;
*slash = 0;
asprintf(&ret, "%s/%s", tmp, rel_name);
free(tmp);
if (!stat(ret, &stattmp))
return ret;
free(ret);
return NULL;
}
int controller_load_block_create(char *type, char *name, yyscan_t scanner)
{
struct controller_load_extra *extra = yyget_extra(scanner);
int ret;
char *prefname = controller_module_prefix_block(name);
return controller_block_create(type, name, extra->va_list_argc, extra->va_list);
ret = controller_block_create(type, prefname, extra->va_list_argc, extra->va_list);
if (!ret)
return 0;
char *file_name = rel2file(scanner, type);
if (!file_name) {
log_send(LOG_T_ERROR,
"Could not find create function or struct for block %s",
type);
return -1;
}
log_send(LOG_T_DEBUG, "Load module '%s' with prefix '%s'",
file_name, prefname);
controller_module_push(prefname);
ret = controller_load(file_name);
controller_module_pop();
log_send(LOG_T_DEBUG, "End of module '%s': %d", file_name, ret);
free(prefname);
return ret;
}
int controller_load_block_param_set(char *block, char *param, yyscan_t scanner)
{
struct controller_load_extra *extra = yyget_extra(scanner);
int ret;
char *prefblock;
prefblock = controller_module_prefix_block(block);
return controller_block_param_set(block, param, extra->va_list_argc, extra->va_list);
ret = controller_block_param_set(prefblock, param,
extra->va_list_argc, extra->va_list);
free(prefblock);
return ret;
}
int controller_load_include(char *file_name)
int controller_load_include(yyscan_t scanner, char *rel_name)
{
int r;
char *file_name = rel2file(scanner, rel_name);
log_send(LOG_T_DEBUG, "Import '%s' (%s)", file_name, rel_name);
if (!file_name) {
log_send(LOG_T_ERROR, "Could not find file");
return -1;
}
log_send(LOG_T_DEBUG, "Include '%s'", file_name);
r = controller_load(file_name);
log_send(LOG_T_DEBUG, "End of include '%s': %d", file_name, r);
free(rel_name);
return r;
}
static int controller_load_import_nr;
static char **controller_load_imports;
int controller_load_import(char *file_name)
int controller_load_import(yyscan_t scanner, char *rel_name)
{
int r, i;
char *realname = realpath(file_name, NULL);
char *file_name = rel2file(scanner, rel_name);
char **imports;
log_send(LOG_T_DEBUG, "Import '%s'", file_name);
log_send(LOG_T_DEBUG, "Import '%s' (%s)", file_name, rel_name);
if (!file_name) {
log_send(LOG_T_ERROR, "Could not find file");
return -1;
}
char *realname = realpath(file_name, NULL);
if (!realname) {
log_send(LOG_T_ERROR, "Could not find realpath");
free(file_name);
return -1;
}
@ -300,6 +386,7 @@ int controller_load_import(char *file_name)
"'%s' ('%s') has already been imported",
file_name, realname);
free(realname);
free(file_name);
return 0;
}
@ -309,6 +396,7 @@ int controller_load_import(char *file_name)
if (!imports) {
log_send(LOG_T_ERROR, "Could not allocate memory for import administration");
free(realname);
free(file_name);
return -1;
}
@ -319,9 +407,29 @@ int controller_load_import(char *file_name)
r = controller_load(file_name);
log_send(LOG_T_DEBUG, "End of import '%s': %d", file_name, r);
free(file_name);
return r;
}
int controller_load_block_connect(char *outblock, char *outterm,
char *inblock, char *interm, int chain)
{
int ret;
char *prefinblock, *prefoutblock;
prefinblock = controller_module_prefix_block(inblock);
prefoutblock = controller_module_prefix_block(outblock);
ret = controller_block_connect(
prefoutblock, outterm, prefinblock, interm, chain);
free(prefinblock);
free(prefoutblock);
return ret;
}
int controller_load_yy_input(char *buf, size_t *readbytes, size_t sizebytes, yyscan_t scanner)
{
struct controller_load_extra *extra = yyget_extra(scanner);


+ 5
- 2
controller/controller/controller_load_int.h View File

@ -42,8 +42,8 @@ void controller_load_var_add_float_array_end(yyscan_t scanner);
void controller_load_var_add_int_array_start(yyscan_t scanner);
void controller_load_var_add_int_array_end(yyscan_t scanner);
void controller_load_frequency(double frequency);
int controller_load_include(char *file_name);
int controller_load_import(char *file_name);
int controller_load_include(yyscan_t scanner, char *file_name);
int controller_load_import(yyscan_t scanner, char *file_name);
char * controller_load_variable_alias_get_block(char *varname);
char * controller_load_variable_alias_get_term(char *varname);
@ -59,4 +59,7 @@ int controller_load_trigger(char *name, yyscan_t scanner);
int controller_load_block_create(char *type, char *name, yyscan_t scanner);
int controller_load_block_param_set(char *block, char *param, yyscan_t scanner);
int controller_load_block_connect(char *outblock, char *outterm,
char *inblock, char *interm, int chain);
#endif /* _INCLUDE_CONTROLLER_LOAD_INT_H_ */

+ 22
- 4
controller/controller/controller_load_parser.y View File

@ -125,7 +125,7 @@ ctrl : aliases
include: INCLUDESYM stringvar
{
if (controller_load_include($2)) {
if (controller_load_include(scanner, $2)) {
yyerror(scanner, "Failed to parse include");
YYERROR;
}
@ -134,7 +134,7 @@ include: INCLUDESYM stringvar
import: IMPORTSYM stringvar
{
if (controller_load_import($2)) {
if (controller_load_import(scanner, $2)) {
yyerror(scanner, "Failed to parse import");
YYERROR;
}
@ -178,7 +178,13 @@ trigger : BRACEOPENSYM
blocks : BLOCKSSYM PARENTHESESOPENSYM doublevar COMMASYM doublevar
{
controller_time_param_set($3, $5);
double frequency = $3;
double delay = $5;
if (frequency == 0.0)
controller_module_parent_time(
&frequency, &delay);
controller_time_param_set(frequency, delay);
}
PARENTHESESCLOSESYM BRACEOPENSYM blocklist BRACECLOSESYM
@ -215,6 +221,18 @@ module : MODULESYM
YYERROR;
}
}
| MODULESYM
PARENTHESESOPENSYM PARENTHESESCLOSESYM
BRACEOPENSYM
BRACEOPENSYM moduleinputlist BRACECLOSESYM
BRACEOPENSYM moduleoutputlist BRACECLOSESYM
BRACECLOSESYM
{
if (controller_module_create(NULL)) {
yyerror(scanner, "Error creating module");
YYERROR;
}
}
;
moduleinputlist : moduleinput
@ -398,7 +416,7 @@ link : BRACEOPENSYM
BOOLSYM
BRACECLOSESYM
{
if (controller_block_connect($2, $4, $6, $8, $10)) {
if (controller_load_block_connect($2, $4, $6, $8, $10)) {
yyerror(scanner, "Error connecting blocks");
YYERROR;
}


+ 70
- 2
controller/controller/controller_module.c View File

@ -18,6 +18,7 @@
#include <controller/controller_module.h>
#include <controller/controller_block.h>
#include <controller/controller_time.h>
#include <log/log.h>
#include <stdlib.h>
@ -25,6 +26,59 @@
#include <stdio.h>
struct controller_module_sf {
struct controller_module_sf *next;
char *prefix;
double frequency;
double delay;
};
static struct controller_module_sf *stack = NULL;
void controller_module_push(char *prefix)
{
struct controller_module_sf *frame;
frame = calloc(1, sizeof(*frame));
frame->next = stack;
stack = frame;
controller_time_param_get(&frame->frequency, &frame->delay);
frame->prefix = prefix;
}
void controller_module_pop(void)
{
struct controller_module_sf *old;
controller_time_param_set(stack->frequency, stack->delay);
old = stack;
stack = old->next;
free(old);
}
void controller_module_parent_time(double *frequency, double *delay)
{
if (stack) {
*frequency = stack->frequency;
*delay = stack->delay;
}
}
char * controller_module_prefix_block(char *name)
{
char *pref;
if (!stack)
return strdup(name);
asprintf(&pref, "%s/%s", stack->prefix, name);
return pref;
}
struct ghost_term {
char *name;
char *realblock;
@ -62,6 +116,14 @@ int controller_module_create(char *name)
{
struct controller_block *module;
int i;
if (stack)
name = stack->prefix;
if (!name) {
log_send(LOG_T_ERROR, "Singleton modules must have a name");
return -1;
}
if (!(module = controller_block_alloc("module", name, 0)))
goto err_alloc;
@ -72,10 +134,13 @@ int controller_module_create(char *name)
goto err_input;
for (i = 0; i < in_term_nr; i++) {
struct controller_block *subblock;
char *realblock;
int j;
module->input[i].name = in_terms[i].name;
subblock = controller_block_find(in_terms[i].realblock);
realblock = controller_module_prefix_block(in_terms[i].realblock);
subblock = controller_block_find(realblock);
free(realblock);
if (!subblock) {
log_send(LOG_T_ERROR, "block %s not found",
in_terms[i].realblock);
@ -109,10 +174,13 @@ int controller_module_create(char *name)
for (i = 0; i < out_term_nr; i++) {
struct controller_block *subblock;
char *realblock;
int j;
module->output[i].name = out_terms[i].name;
subblock = controller_block_find(out_terms[i].realblock);
realblock = controller_module_prefix_block(out_terms[i].realblock);
subblock = controller_block_find(realblock);
free(realblock);
if (!subblock) {
log_send(LOG_T_ERROR, "block %s not found",
out_terms[i].realblock);


+ 5
- 0
controller/controller/controller_module.h View File

@ -23,4 +23,9 @@ int controller_module_create(char *name);
int controller_module_input_add(char *name, char *blockname, char *inputname);
int controller_module_output_add(char *name, char *blockname, char *outputname);
void controller_module_push(char *prefix);
void controller_module_pop(void);
void controller_module_parent_time(double *frequency, double *delay);
char * controller_module_prefix_block(char *name);
#endif /* _INCLUDE_CONTROLLER_MODULE_H_ */

+ 6
- 0
controller/controller/controller_time.c View File

@ -51,6 +51,12 @@ void controller_time_param_set(double frequency, double delay)
param_delay = delay;
}
void controller_time_param_get(double *frequency, double *delay)
{
*frequency = param_frequency;
*delay = param_delay;
}
struct controller_time *controller_time_get(void)
{
struct controller_time *entry;


+ 1
- 0
controller/controller/controller_time.h View File

@ -31,6 +31,7 @@ extern uint32_t controller_samplenr;
void controller_time_param_set(double frequency, double delay);
void controller_time_param_get(double *frequency, double *delay);
struct controller_time *controller_time_get();


+ 1
- 0
controller/test/build.mk View File

@ -32,6 +32,7 @@ SRCS += $(TEST_BLOCK_SRCS)
CTRL_TESTS += \
$(DIR)/test.ctrl \
$(DIR)/test_import.ctrl \
$(DIR)/test_module.ctrl \
$(DIR)/test_multifrequency.ctrl \


+ 36
- 0
controller/test/test_import.ctrl View File

@ -0,0 +1,36 @@
# Test import keyword
trigger {
{ "immediate" }
}
blocks (100.0, 0.0) {
{ "test_input_float", "in" }
{ "test_output_float", "out" }
}
import "controller/test/test_import_gain1.ctrl"
import "test_import_gain2.ctrl"
links {
{ "in", "value", "gain1", "in", true }
{ "gain1", "out", "gain2", "in", true }
{ "gain2", "out", "out", "value", true }
}
params {
{ "gain1", "gain", 5.0 }
{ "gain2", "gain", 2.0 }
{ "in", "value", 10,
(float) { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 }
}
{ "out", "value", 10,
(float) { 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0 },
(float) { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }
}
}

+ 4
- 0
controller/test/test_import_gain1.ctrl View File

@ -0,0 +1,4 @@
blocks (100.0, 0.0) {
{ "gain", "gain1" }
}

+ 4
- 0
controller/test/test_import_gain2.ctrl View File

@ -0,0 +1,4 @@
blocks (100.0, 0.0) {
{ "gain", "gain2" }
}

+ 32
- 2
controller/test/test_module.ctrl View File

@ -6,6 +6,7 @@ trigger {
blocks (100.0, 0.0) {
{ "test_input_float", "in" }
{ "test_input_float", "in2" }
{ "gain", "gain1" }
{ "gain", "gain2" }
@ -19,16 +20,30 @@ blocks (100.0, 0.0) {
}
}
{ "test_module_gg.ctrl", "gg1" }
{ "test_module_gg.ctrl", "gg2" }
{ "test_module_ggn.ctrl", "ggn" }
{ "test_output_float", "out" }
{ "test_output_float", "out_gg1" }
{ "test_output_float", "out_gg2" }
{ "test_output_float", "out_ggn" }
}
links {
{ "in", "value", "gaingain", "in", true }
{ "in", "value", "gaingain", "in", true }
{ "in", "value", "gg1", "in", true }
{ "in2", "value", "gg2", "in", true }
{ "in", "value", "ggn", "in", true }
{ "gain1", "out", "gain2", "in", true }
{ "gaingain", "out", "out", "value", true }
{ "gaingain", "out", "out", "value", true }
{ "gg1", "out", "out_gg1", "value", true }
{ "gg2", "out", "out_gg2", "value", true }
{ "ggn", "out", "out_ggn", "value", true }
}
params {
@ -38,8 +53,23 @@ params {
{ "in", "value", 10,
(float) { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 }
}
{ "in2", "value", 10,
(float) { -1.0, -2.0, -3.0, -4.0, -5.0, -6.0, -7.0, -8.0, -9.0, -10.0 }
}
{ "out", "value", 10,
(float) { 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0 },
(float) { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }
}
{ "out_gg1", "value", 10,
(float) { 100.0, 200.0, 300.0, 400.0, 500.0, 600.0, 700.0, 800.0, 900.0, 1000.0 },
(float) { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }
}
{ "out_gg2", "value", 10,
(float) { -100.0, -200.0, -300.0, -400.0, -500.0, -600.0, -700.0, -800.0, -900.0, -1000.0 },
(float) { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }
}
{ "out_ggn", "value", 10,
(float) { 10000.0, 10000.0, 30000.0, 30000.0, 50000.0, 50000.0, 70000.0, 70000.0, 90000.0, 90000.0 },
(float) { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }
}
}

+ 16
- 0
controller/test/test_module_gg.ctrl View File

@ -0,0 +1,16 @@
blocks(0.0, 0.0) {
{ "gain", "gain_internal" }
module () {
{
{ "in", "gain_internal", "in" }
}
{
{ "out", "gain_internal", "out" }
}
}
}
params {
{ "gain_internal", "gain", 100.0 }
}

+ 17
- 0
controller/test/test_module_ggn.ctrl View File

@ -0,0 +1,17 @@
blocks(50.0, 0.0) {
{ "test_module_gg.ctrl", "gg_nested1" }
{ "test_module_gg.ctrl", "gg_nested2" }
module () {
{
{ "in", "gg_nested1", "in" }
}
{
{ "out", "gg_nested2", "out" }
}
}
}
links {
{ "gg_nested1", "out", "gg_nested2", "in", true }
}

Loading…
Cancel
Save