From d04cbaf014289c14ead75404427143c4f7a3ccd2 Mon Sep 17 00:00:00 2001 From: Michal Lenc Date: Sun, 5 Jan 2025 15:07:21 +0100 Subject: [PATCH] toolbox/supsisim: refactor SHV part of the code This refactors SHV part of the code. The SHV tree generation and client connection is moved to a separate subdirectory and unified with Class access. The goal is to provide more clear access to SHV package and simplify the future enhancement and maintenance of the code. The functionality of SHV generation/connection is not changed. Signed-off-by: Michal Lenc --- toolbox/supsisim/supsisim/RCPgen.py | 18 +- toolbox/supsisim/supsisim/SHVgen.py | 402 ------------ toolbox/supsisim/supsisim/client.py | 151 ----- toolbox/supsisim/supsisim/editor.py | 10 +- toolbox/supsisim/supsisim/scene.py | 6 +- toolbox/supsisim/supsisim/shv/__init__.py | 9 + toolbox/supsisim/supsisim/shv/client.py | 191 ++++++ toolbox/supsisim/supsisim/shv/generator.py | 704 +++++++++++++++++++++ 8 files changed, 917 insertions(+), 574 deletions(-) delete mode 100644 toolbox/supsisim/supsisim/SHVgen.py delete mode 100644 toolbox/supsisim/supsisim/client.py create mode 100644 toolbox/supsisim/supsisim/shv/__init__.py create mode 100644 toolbox/supsisim/supsisim/shv/client.py create mode 100644 toolbox/supsisim/supsisim/shv/generator.py diff --git a/toolbox/supsisim/supsisim/RCPgen.py b/toolbox/supsisim/supsisim/RCPgen.py index 34cf0ec9..baee9d09 100644 --- a/toolbox/supsisim/supsisim/RCPgen.py +++ b/toolbox/supsisim/supsisim/RCPgen.py @@ -20,7 +20,7 @@ import copy import sys from supsisim.RCPblk import RCPblk -from supsisim.SHVgen import genSHVtree, genSHVcode, genSHVheader, genSHVend +from .shv import ShvTreeGenerator def genCode(model, Tsamp, blocks, rkstep = 10): """Generate C-Code @@ -68,7 +68,8 @@ def genCode(model, Tsamp, blocks, rkstep = 10): N = size(Blocks) - genSHVheader(f, model, N) + shv_generator = ShvTreeGenerator(f, model, Blocks) + shv_generator.generate_header() totContBlk = 0 for blk in Blocks: @@ -160,15 +161,8 @@ def genCode(model, Tsamp, blocks, rkstep = 10): f.write("\n\n") - Blks = [] - for n in range(0,N): - Blks.append(Blocks[n].name) - - BlksOrigin = copy.deepcopy(Blks) - Blks.sort() - if (environ["SHV_TREE_TYPE"] == "GSA_STATIC") and (environ["SHV_USED"] == "True"): - genSHVtree(f, Blocks, Blks) + shv_generator.generate_tree() f.write("/* Initialization function */\n\n") strLn = "void " + model + "_init(void)\n" @@ -227,7 +221,7 @@ def genCode(model, Tsamp, blocks, rkstep = 10): f.write("\n") if environ["SHV_USED"] == "True": - genSHVcode(f, model, Blocks, Blks) + shv_generator.generate_code() f.write("/* Set initial outputs */\n\n") @@ -294,7 +288,7 @@ def genCode(model, Tsamp, blocks, rkstep = 10): f.write(strLn) if environ["SHV_USED"] == "True": - genSHVend(f, model) + shv_generator.generate_end() for n in range(0,N): blk = Blocks[n] diff --git a/toolbox/supsisim/supsisim/SHVgen.py b/toolbox/supsisim/supsisim/SHVgen.py deleted file mode 100644 index 87b47003..00000000 --- a/toolbox/supsisim/supsisim/SHVgen.py +++ /dev/null @@ -1,402 +0,0 @@ -""" -This is a procedural interface to generate silicon-heaven tree. - -michallenc@seznam.cz - -The following commands are provided: - - genSHVheader - Create includes and defines - genSHVtree - Create static SHV tree in generated C code - genSHVcode - Create C code providing tree init - genSHVend - Provide call for tree destruction -""" - -from numpy import size -from os import environ -import copy - -def genSHVheader(f, model, N): - if environ["SHV_USED"] == "True": - strLn = "#define CONF_SHV_USED 1\n\n" - else: - strLn = "#undef CONF_SHV_USED\n\n" - f.write(strLn) - - strLn = "#ifdef CONF_SHV_USED\n" - strLn += "#include \n" - strLn += "#include \n" - strLn += "#include \n" - strLn += "#include \n" - strLn += "#include \n\n" - f.write(strLn) - - if environ["SHV_TREE_TYPE"] == "GSA": - strLn = "#define CONF_SHV_TREE_TYPE 1\n" - strLn += "#undef CONF_SHV_TREE_STATIC\n\n" - elif environ["SHV_TREE_TYPE"] == "GSA_STATIC": - strLn = "#define CONF_SHV_TREE_TYPE 3\n" - strLn += "#define CONF_SHV_TREE_STATIC 1\n\n" - else: - strLn = "#define CONF_SHV_TREE_TYPE 0\n" - strLn += "#undef CONF_SHV_TREE_STATIC\n" - - strLn += "#endif /* CONF_SHV_USED */\n\n" - f.write(strLn) - - if environ["SHV_USED"] == "True": - f.write("/* SHV related function and structres */\n\n") - f.write("#ifdef CONF_SHV_USED\n") - f.write("shv_con_ctx_t *shv_tree_init(python_block_name_map * block_map, const shv_node_t *static_root, int mode);\n") - f.write("void shv_tree_end(shv_con_ctx_t *ctx, int mode);\n\n") - - strLn = "python_block_name_map block_name_map_" + model + ";\n" - strLn += "python_block_name_entry block_name_entry_" + model + "[" + str(N) + "];\n" - strLn += "static shv_con_ctx_t *" + model + "_ctx;\n" - strLn += "#endif /* CONF_SHV_USED */\n\n" - f.write(strLn) - -def genSHVtree(f, Blks, BlksOrdered): - f.write("#ifdef CONF_SHV_TREE_STATIC\n") - - #f.write("extern const shv_dmap_t shv_double_dmap;\nextern const shv_dmap_t shv_blk_dmap;\nextern const shv_dmap_t shv_root_dmap;\n\n") - - N = size(Blks) - - hasSystemInputs = 0 - hasSystemOutputs = 0 - hasBlocks = 0 - - BlksNames = [] - for i in range(0, N): - BlksNames.append(Blks[i].name) - - for n in range(0, N): - hasRealPars = 0 - hasInputs = 0 - hasOutpus = 0 - index = BlksNames.index(BlksOrdered[n]) - - strLn = "" - if ((Blks[index].fcn != "shv_input") and (Blks[index].fcn != "shv_output")): - hasBlocks = 1 - if (size(Blks[index].realPar) != 0): - hasRealPars = 1 - - realParNames= [] - - if (size(Blks[index].realPar) == size(Blks[index].realParNames)): - for i in range(0,size(Blks[index].realPar)): - realParNames.append(Blks[index].realParNames[i]) - else: - for i in range(0,size(Blks[index].realPar)): - realParNames.append("double" + str(i)) - - realParNamesOrdered = copy.deepcopy(realParNames) - realParNamesOrdered.sort() - - for i in range(0, size(Blks[index].realPar)): - indexPar = realParNames.index(realParNamesOrdered[i]) - strLn += "const shv_node_typed_val_t shv_node_typed_val_blk" + str(n) + "_par" + str(i) + " = {\n" + \ - " .shv_node = {.name = \"" + str(realParNames[indexPar]) + "\",\n" + \ - " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_double_dmap),\n" + \ - " },\n" + \ - " .val_ptr = &realPar_" + str(index) + "[" + str(indexPar) + "],\n" + \ - " .type_name = \"double\",\n};\n\n" - f.write(strLn) - strLn = "const shv_node_typed_val_t *const shv_node_typed_val_blk" + str(n) + "_pars" + "[] = {\n" - for i in range(0, size(Blks[index].realPar) ): - strLn += " &shv_node_typed_val_blk" + str(n) + "_par" + str(i) + ",\n" - - strLn += "};\n\n" - f.write(strLn) - - strLn = "const shv_node_t shv_node_blk" + str(n) + "_par = {\n" + \ - " .name = \"parameters\",\n" + \ - " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_blk_dmap),\n" + \ - " .children = {.mode = CONF_SHV_TREE_TYPE,\n" - if (hasRealPars): - strLn+= " .list = {.gsa = {.root = {\n" + \ - " .items = (void **)shv_node_typed_val_blk" + str(n) + "_pars,\n" + \ - " .count = sizeof(shv_node_typed_val_blk" + str(n) + "_pars)/sizeof(shv_node_typed_val_blk" + str(n) + "_pars[0]),\n" + \ - " .alloc_count = 0,}\n" + \ - "}}" - strLn += "}};\n\n" - f.write(strLn) - - if (size(Blks[index].pin) != 0): - hasInputs = 1 - strLn = "" - for i in range(0, size(Blks[index].pin)): - strLn += "const shv_node_typed_val_t shv_node_typed_val_blk" + str(n) + "_in" + str(i) + " = {\n" + \ - " .shv_node = {.name = \"input" + str(i) + "\",\n" + \ - " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_double_read_only_dmap),\n" + \ - " },\n" + \ - " .val_ptr = Node_" + str(Blks[index].pin[i]) + ",\n" + \ - " .type_name = \"double\",\n};\n\n" - f.write(strLn) - strLn = "const shv_node_typed_val_t *const shv_node_typed_val_blk" + str(n) + "_ins" + "[] = {\n" - for i in range(0, size(Blks[index].pin) ): - strLn += " &shv_node_typed_val_blk" + str(n) + "_in" + str(i) + ",\n" - strLn += "};\n\n" - f.write(strLn) - - strLn = "const shv_node_t shv_node_blk" + str(n) + "_in = {\n" + \ - " .name = \"inputs\",\n" + \ - " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_blk_dmap),\n" + \ - " .children = {.mode = CONF_SHV_TREE_TYPE,\n" - if (hasInputs): - strLn+= " .list = {.gsa = {.root = {\n" + \ - " .items = (void **)shv_node_typed_val_blk" + str(n) + "_ins,\n" + \ - " .count = sizeof(shv_node_typed_val_blk" + str(n) + "_ins)/sizeof(shv_node_typed_val_blk" + str(n) + "_ins[0]),\n" + \ - " .alloc_count = 0,}\n" + \ - "}}" - strLn += "}};\n\n" - f.write(strLn) - - if (size(Blks[index].pout) != 0): - hasOutpus = 1 - strLn = "" - for i in range(0, size(Blks[index].pout)): - strLn += "const shv_node_typed_val_t shv_node_typed_val_blk" + str(n) + "_out" + str(i) + " = {\n" + \ - " .shv_node = {.name = \"output" + str(i) + "\",\n" + \ - " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_double_read_only_dmap),\n" + \ - " },\n" + \ - " .val_ptr = Node_" + str(Blks[index].pout[i]) + ",\n" + \ - " .type_name = \"double\",\n};\n\n" - f.write(strLn) - strLn = "const shv_node_typed_val_t *const shv_node_typed_val_blk" + str(n) + "_outs" + "[] = {\n" - for i in range(0, size(Blks[index].pout) ): - strLn += " &shv_node_typed_val_blk" + str(n) + "_out" + str(i) + ",\n" - strLn += "};\n\n" - f.write(strLn) - - strLn = "const shv_node_t shv_node_blk" + str(n) + "_out = {\n" + \ - " .name = \"outputs\",\n" + \ - " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_blk_dmap),\n" + \ - " .children = {.mode = CONF_SHV_TREE_TYPE,\n" - if (hasOutpus): - strLn+= " .list = {.gsa = {.root = {\n" + \ - " .items = (void **)shv_node_typed_val_blk" + str(n) + "_outs,\n" + \ - " .count = sizeof(shv_node_typed_val_blk" + str(n) + "_outs)/sizeof(shv_node_typed_val_blk" + str(n) + "_outs[0]),\n" + \ - " .alloc_count = 0,}\n" + \ - "}}" - strLn += "}};\n\n" - f.write(strLn) - - strLn = "const shv_node_t *const shv_node_blk" + str(n) + "_items" + "[] = {\n" - strLn += " &shv_node_blk" + str(n) + "_in,\n" - strLn += " &shv_node_blk" + str(n) + "_out,\n" - strLn += " &shv_node_blk" + str(n) + "_par\n" - strLn += "};\n\n" - f.write(strLn) - - strLn = "const shv_node_t shv_node_blk" + str(n) + " = {\n" + \ - " .name = \"" + str(Blks[index].name) + "\",\n" + \ - " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_blk_dmap),\n" + \ - " .children = {.mode = CONF_SHV_TREE_TYPE,\n" + \ - " .list = {.gsa = {.root = {\n" + \ - " .items = (void **)shv_node_blk" + str(n) + "_items,\n" + \ - " .count = sizeof(shv_node_blk" + str(n) + "_items)/sizeof(shv_node_blk" + str(n) + "_items[0]),\n" + \ - " .alloc_count = 0,}\n" + \ - "}}}};\n\n" - f.write(strLn) - - strLn = "" - if (Blks[index].fcn == "shv_input"): - hasSystemInputs = 1 - # we have editable outputs (SHV input block) - for i in range(0, size(Blks[index].pout)): - strLn += "const shv_node_typed_val_t shv_node_typed_val_blk" + str(n) + "_sysIn" + str(i) + " = {\n" + \ - " .shv_node = {.name = \"input" + str(i) + "\",\n" + \ - " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_double_dmap),\n" + \ - " },\n" + \ - " .val_ptr = Node_" + str(Blks[index].pout[i]) + ",\n" + \ - " .type_name = \"double\",\n};\n\n" - f.write(strLn) - strLn = "const shv_node_typed_val_t *const shv_node_typed_val_blk" + str(n) + "_sysIns" + "[] = {\n" - for i in range(0, size(Blks[index].pout) ): - strLn += " &shv_node_typed_val_blk" + str(n) + "_sysIn" + str(i) + ",\n" - - strLn += "};\n\n" - f.write(strLn) - - strLn = "const shv_node_t shv_node_blk" + str(n) + "_sysIns = {\n" + \ - " .name = \"" + str(Blks[index].name) + "\",\n" + \ - " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_blk_dmap),\n" + \ - " .children = {.mode = CONF_SHV_TREE_TYPE,\n" + \ - " .list = {.gsa = {.root = {\n" + \ - " .items = (void **)shv_node_typed_val_blk" + str(n) + "_sysIns,\n" + \ - " .count = sizeof(shv_node_typed_val_blk" + str(n) + "_sysIns)/sizeof(shv_node_typed_val_blk" + str(n) + "_sysIns[0]),\n" + \ - " .alloc_count = 0,}\n" + \ - "}}}};\n\n" - f.write(strLn) - - if (Blks[index].fcn == "shv_output"): - hasSystemOutputs = 1 - # we have editable inputs (SHV output block) - for i in range(0, size(Blks[index].pin)): - strLn += "const shv_node_typed_val_t shv_node_typed_val_blk" + str(n) + "_sysOut" + str(i) + " = {\n" + \ - " .shv_node = {.name = \"output" + str(i) + "\",\n" + \ - " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_double_read_only_dmap),\n" + \ - " },\n" + \ - " .val_ptr = Node_" + str(Blks[index].pin[i]) + ",\n" + \ - " .type_name = \"double\",\n};\n\n" - f.write(strLn) - strLn = "const shv_node_typed_val_t *const shv_node_typed_val_blk" + str(n) + "_sysOuts" + "[] = {\n" - for i in range(0, size(Blks[index].pin) ): - strLn += " &shv_node_typed_val_blk" + str(n) + "_sysOut" + str(i) + ",\n" - - strLn += "};\n\n" - f.write(strLn) - - strLn = "const shv_node_t shv_node_blk" + str(n) + "_sysOuts = {\n" + \ - " .name = \"" + str(Blks[index].name) + "\",\n" + \ - " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_blk_dmap),\n" + \ - " .children = {.mode = CONF_SHV_TREE_TYPE,\n" + \ - " .list = {.gsa = {.root = {\n" + \ - " .items = (void **)shv_node_typed_val_blk" + str(n) + "_sysOuts,\n" + \ - " .count = sizeof(shv_node_typed_val_blk" + str(n) + "_sysOuts)/sizeof(shv_node_typed_val_blk" + str(n) + "_sysOuts[0]),\n" + \ - " .alloc_count = 0,}\n" + \ - "}}}};\n\n" - f.write(strLn) - - if (hasBlocks): - strLn = "const shv_node_t *const shv_node_blks_list[] = {\n" - for n in range(0, N): - index = BlksNames.index(BlksOrdered[n]) - if ((Blks[index].fcn != "shv_input") and (Blks[index].fcn != "shv_output")): - strLn += " &shv_node_blk" + str(n) + ",\n" - strLn += "};\n\n" - f.write(strLn) - - strLn = "const shv_node_t shv_node_blks = {\n" + \ - " .name = \"blocks\",\n" + \ - " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_root_dmap),\n" + \ - " .children = {.mode = CONF_SHV_TREE_TYPE,\n" - if (hasBlocks): - strLn += " .list = {.gsa = {.root = {\n" + \ - " .items = (void **)shv_node_blks_list,\n" + \ - " .count = sizeof(shv_node_blks_list)/sizeof(shv_node_blks_list[0]),\n" + \ - " .alloc_count = 0,}\n" + \ - "}}" - strLn += "}};\n\n" - f.write(strLn) - - if (hasSystemInputs): - strLn = "const shv_node_t *const shv_node_blks_inputs[] = {\n" - for n in range(0, N): - index = BlksNames.index(BlksOrdered[n]) - if ((size(Blks[index].pout) != 0) and (Blks[index].fcn == "shv_input")): - strLn += " &shv_node_blk" + str(n) + "_sysIns,\n" - strLn += "};\n\n" - f.write(strLn) - - strLn = "const shv_node_t shv_node_inputs = {\n" + \ - " .name = \"inputs\",\n" + \ - " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_root_dmap),\n" + \ - " .children = {.mode = CONF_SHV_TREE_TYPE,\n" - if (hasSystemInputs): - strLn += " .list = {.gsa = {.root = {\n" + \ - " .items = (void **)shv_node_blks_inputs,\n" + \ - " .count = sizeof(shv_node_blks_inputs)/sizeof(shv_node_blks_inputs[0]),\n" + \ - " .alloc_count = 0,}\n" + \ - "}}" - strLn += "}};\n\n" - f.write(strLn) - - if (hasSystemOutputs): - strLn = "const shv_node_t *const shv_node_blks_outputs[] = {\n" - for n in range(0, N): - index = BlksNames.index(BlksOrdered[n]) - if ((size(Blks[index].pin) != 0) and (Blks[index].fcn == "shv_output")): - strLn += " &shv_node_blk" + str(n) + "_sysOuts,\n" - strLn += "};\n\n" - f.write(strLn) - - strLn = "const shv_node_t shv_node_outputs = {\n" + \ - " .name = \"outputs\",\n" + \ - " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_root_dmap),\n" + \ - " .children = {.mode = CONF_SHV_TREE_TYPE,\n" - if (hasSystemOutputs): - strLn += " .list = {.gsa = {.root = {\n" + \ - " .items = (void **)shv_node_blks_outputs,\n" + \ - " .count = sizeof(shv_node_blks_outputs)/sizeof(shv_node_blks_outputs[0]),\n" + \ - " .alloc_count = 0,}\n" + \ - "}}" - strLn += "}};\n\n" - f.write(strLn) - - strLn = "const shv_node_t *const shv_tree_root_items[] = {\n" + \ - " &shv_node_blks,\n" + \ - " &shv_node_inputs,\n" + \ - " &shv_node_outputs,\n};\n\n" - f.write(strLn) - - strLn = "const shv_node_t shv_tree_root = {\n" + \ - " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_root_dmap),\n" + \ - " .children = {.mode = CONF_SHV_TREE_TYPE,\n" + \ - " .list = {.gsa = {.root = {\n" + \ - " .items = (void **)shv_tree_root_items,\n" + \ - " .count = sizeof(shv_tree_root_items)/sizeof(shv_tree_root_items[0]),\n" + \ - " .alloc_count = 0,}\n" + \ - "}}}};\n\n" - f.write(strLn) - - f.write("#endif /* CONF_SHV_TREE_STATIC */") - -def genSHVcode(f, model, Blks, BlksOrdered): - strLn = "#ifdef CONF_SHV_USED\n" - strLn += " setenv(\"SHV_BROKER_IP\", \"" + environ["SHV_BROKER_IP"] + "\", 0);\n" - strLn += " setenv(\"SHV_BROKER_PORT\", \"" + environ["SHV_BROKER_PORT"] + "\", 0);\n" - strLn += " setenv(\"SHV_BROKER_USER\", \"" + environ["SHV_BROKER_USER"] + "\", 0);\n" - strLn += " setenv(\"SHV_BROKER_PASSWORD\", \"" + environ["SHV_BROKER_PASSWORD"] + "\", 0);\n" - strLn += " setenv(\"SHV_BROKER_DEV_ID\", \"" + environ["SHV_BROKER_DEV_ID"] + "\", 0);\n" - strLn += " setenv(\"SHV_BROKER_MOUNT\", \"" + environ["SHV_BROKER_MOUNT"] + "\", 0);\n\n" - f.write(strLn) - - f.write("/* SHV structures definition */\n\n") - - N = size(Blks) - - BlksNames = [] - for i in range(0, N): - BlksNames.append(Blks[i].name) - - strLn = "" - for n in range(0,N): - index = BlksNames.index(BlksOrdered[n]) - strLn += " block_name_entry_" + model + "[" + str(n) + "].block_name = \"" + BlksOrdered[n] + "\";\n" - strLn += " block_name_entry_" + model + "[" + str(n) + "].block_idx = " + str(index) + ";\n" - if (Blks[index].fcn == 'shv_input'): - strLn += " block_name_entry_" + model + "[" + str(n) + "].system_inputs = " + str(1) + ";\n" - else: - strLn += " block_name_entry_" + model + "[" + str(n) + "].system_inputs = " + str(0) + ";\n" - if (Blks[index].fcn == 'shv_output'): - strLn += " block_name_entry_" + model + "[" + str(n) + "].system_outputs = " + str(1) + ";\n" - else: - strLn += " block_name_entry_" + model + "[" + str(n) + "].system_outputs = " + str(0) + ";\n" - - strLn += "\n" - f.write(strLn) - - strLn = " block_name_map_" + model + ".blocks_count = " + str(N) + ";\n" - strLn += " block_name_map_" + model + ".blocks = " + "block_name_entry_" + model + ";\n" - strLn += " block_name_map_" + model + ".block_structure = block_" + model + ";\n\n" - f.write(strLn) - - f.write("/* Call shv_tree_init() to initialize SHV tree */\n\n") - - if (environ["SHV_TREE_TYPE"] != "GSA_STATIC"): - strLn = " const shv_node_t shv_tree_root = {};\n\n" - f.write(strLn) - - strLn = " " + model + "_ctx = shv_tree_init(&block_name_map_" + model + ", &shv_tree_root, CONF_SHV_TREE_TYPE);\n\n" - f.write(strLn) - - f.write("#endif /* CONF_SHV_USED */\n\n") - -def genSHVend(f, model): - strLn = "#ifdef CONF_SHV_USED\n" - strLn += " shv_tree_end(" + model + "_ctx, CONF_SHV_TREE_TYPE);\n" - strLn += "#endif /* CONF_SHV_USED */\n\n" - f.write(strLn) \ No newline at end of file diff --git a/toolbox/supsisim/supsisim/client.py b/toolbox/supsisim/supsisim/client.py deleted file mode 100644 index 576507dd..00000000 --- a/toolbox/supsisim/supsisim/client.py +++ /dev/null @@ -1,151 +0,0 @@ -#!/usr/bin/env python3 -import asyncio -from pydoc import locate -from threading import Thread - -from shv import RpcUrl, SimpleClient, RpcError, SHVType - - -def _start_background_loop(loop: asyncio.AbstractEventLoop) -> None: - asyncio.set_event_loop(loop) - try: - loop.run_forever() - finally: - print("Ending connection loop...") - for task in asyncio.all_tasks(): - task.cancel() - - print("Remaining tasks canceled...") - loop.close() - print("Ending connection loop, all Done") - -async def _disconnect_client(client: SimpleClient): - if await _is_connected(client): - await client.disconnect() - -async def _connect_client(user: str, addr: str, port: str, password: str) -> SimpleClient | None: - url: RpcUrl = RpcUrl.parse("tcp://{}@{}:{}?password={}".format(user, addr, port, password)) - - print("Connection to SHV broker: ", url.to_url()) - return await SimpleClient.connect(url) - - -async def _get_parameter_value(client: SimpleClient, mount_point:str, device_id: str, item: str, paramName: str) -> SHVType|None: - callUrl = "{}/{}/blocks/{}/parameters/{}".format(mount_point, device_id, paramName, item) - try: - result = await client.call(callUrl, "get") - return result - except RpcError as e: - print("Can't read parameter ", paramName) - print(e) - return None - -async def _set_parameter_value(client: SimpleClient, mount_point:str, device_id: str, item: str, paramName: str, paramVal: SHVType): - callUrl = "{}/{}/blocks/{}/parameters/{}".format(mount_point, device_id, paramName, item) - # print("Set param url: ", callUrl) - try: - return await client.call(callUrl, "set", paramVal) - except RpcError as e: - print("Can't set parameter ", paramName) - print(e) - -async def _is_connected(client: SimpleClient) -> bool: - return client.client.connected - - -class BrokerConnection: - def __init__(self): - self.asyncio_loop = asyncio.new_event_loop() - self.asyncio_thread = Thread(target=_start_background_loop, args=(self.asyncio_loop,), daemon=True) - self.client: SimpleClient | None = None - self.addr: str | None = None - self.port: str | None = None - self.user: str | None = None - self.password: str | None = None - self.device_id: str | None = None - self.mount_point: str | None = None - - self.asyncio_thread.start() - - def __del__(self): - self.asyncio_loop.stop() - - - def _connect(self): - print("Connecting to broker...") - try: - client = asyncio.run_coroutine_threadsafe(_connect_client(self.user, self.addr, self.port, self.password), self.asyncio_loop).result() - except: - print("No connection to broker") - return - - if client is None: - print("No connection to broker") - - - self.client = client - - print("Connected to broker.") - - def _disconnect(self): - if self.client is None: - return - print("Disconnecting from broker...") - asyncio.run_coroutine_threadsafe(_disconnect_client(self.client), self.asyncio_loop).result() - - self.client = None - - print("Disconnected from broker.") - - def _get_connection(self): - if self.client is None or not asyncio.run_coroutine_threadsafe(_is_connected(self.client), self.asyncio_loop).result(): - self._connect() - - return self.client - - def update_parameters_and_connect(self, addr: str, port: str, user: str, password: str, device_id: str, mount_point: str): - - are_values_updated = (self.addr != addr or - self.port != port or - self.user != user or - self.password != password or - self.device_id != device_id or - self.mount_point != mount_point) - - - self.addr = addr - self.port = port - self.user = user - self.password = password - self.device_id = device_id - self.mount_point = mount_point - - if are_values_updated: - self._disconnect() - - if self.client is None: - self._connect() - - def isConnected(self)-> bool: - if self.client is None: - return False - - return asyncio.run_coroutine_threadsafe(_is_connected(self.client), self.asyncio_loop).result() - - - def getParameterValue(self, item: str, paramName: str) -> SHVType|None: - client = self._get_connection() - return asyncio.run_coroutine_threadsafe( - _get_parameter_value(client, self.mount_point, self.device_id, item, paramName), - self.asyncio_loop - ).result() - - def setPrameterValue(self, item: str, paramName: str, paramVal: SHVType): - client = self._get_connection() - asyncio.run_coroutine_threadsafe( - _set_parameter_value(client, self.mount_point, self.device_id, item, paramName, paramVal), - self.asyncio_loop - ).result() - - def disconnect(self): - self._disconnect() diff --git a/toolbox/supsisim/supsisim/editor.py b/toolbox/supsisim/supsisim/editor.py index 9a79b5dc..f55da281 100644 --- a/toolbox/supsisim/supsisim/editor.py +++ b/toolbox/supsisim/supsisim/editor.py @@ -8,10 +8,8 @@ import supsisim.RCPDlg as pDlg from supsisim.const import GRID, DB, DP from supsisim.node import Node -from supsisim.client import * -import numpy as np import json -from shv import SHVDecimal, SHVFloat +from shv import SHVDecimal from decimal import Decimal, ROUND_DOWN @@ -233,7 +231,7 @@ def shvAction(self): connection = self.scene.getBrokerConnection() - if not connection.isConnected(): + if not connection.is_connected(): dlg = QMessageBox() dlg.setWindowTitle("Warning!") dlg.setText("No connection to broker") @@ -255,7 +253,7 @@ def shvAction(self): for i in range(1,len(items)): par = items[i].split(':') if par[2].replace(" ", "") == "double": - res = connection.getParameterValue(par[0], name) + res = connection.get_parameter_value(par[0], name) par[1] = str(float(res)) items[i] = ':'.join(par) name = item.name.replace(' ','_') + '_' + str(item.ident) @@ -304,7 +302,7 @@ def shvAction(self): print("Wrong data type") else: continue - connection.setPrameterValue(par[0], name, parameter) + connection.set_parameter_value(par[0], name, parameter) else: self.scene.clearLastUndo() diff --git a/toolbox/supsisim/supsisim/scene.py b/toolbox/supsisim/supsisim/scene.py index 721f5f25..c227e656 100644 --- a/toolbox/supsisim/supsisim/scene.py +++ b/toolbox/supsisim/supsisim/scene.py @@ -6,7 +6,7 @@ from supsisim.connection import Connection from supsisim.dialg import RTgenDlg, SHVDlg from supsisim.const import VERSION, pyrun, TEMP, respath, BWmin -from supsisim.client import BrokerConnection +from .shv import ShvClient from lxml import etree import os import subprocess @@ -61,7 +61,7 @@ def __init__(self, main, parent=None): self.SHV = SHVInstance(self.mainw.filename) - self.brokerConnection = BrokerConnection() + self.brokerConnection = ShvClient() self.undoList = [] @@ -754,7 +754,7 @@ def debugInfo(self): for item in dgmConnections: print(item) - def getBrokerConnection(self) -> BrokerConnection: + def getBrokerConnection(self) -> ShvClient: shv = self.SHV self.brokerConnection.update_parameters_and_connect(shv.ip, shv.port, shv.user, shv.passw, shv.devid, shv.mount) diff --git a/toolbox/supsisim/supsisim/shv/__init__.py b/toolbox/supsisim/supsisim/shv/__init__.py new file mode 100644 index 00000000..f5823984 --- /dev/null +++ b/toolbox/supsisim/supsisim/shv/__init__.py @@ -0,0 +1,9 @@ +"""Implementation of SHV tree generation and communication via pySHV.""" + +from .client import ShvClient +from .generator import ShvTreeGenerator + +__all__ = [ + "ShvClient", + "ShvTreeGenerator", +] diff --git a/toolbox/supsisim/supsisim/shv/client.py b/toolbox/supsisim/supsisim/shv/client.py new file mode 100644 index 00000000..e2e1ce5e --- /dev/null +++ b/toolbox/supsisim/supsisim/shv/client.py @@ -0,0 +1,191 @@ +""" +SHV client. +""" + +import asyncio +from threading import Thread + +from shv import RpcUrl, SimpleClient, RpcError, SHVType + + +def _start_background_loop(loop: asyncio.AbstractEventLoop) -> None: + asyncio.set_event_loop(loop) + try: + loop.run_forever() + finally: + print("Ending connection loop...") + for task in asyncio.all_tasks(): + task.cancel() + + print("Remaining tasks canceled...") + loop.close() + print("Ending connection loop, all Done") + + +async def _disconnect_client(client: SimpleClient): + if await _is_connected(client): + await client.disconnect() + + +async def _connect_client( + user: str, addr: str, port: str, password: str +) -> SimpleClient | None: + url: RpcUrl = RpcUrl.parse(f"tcp://{user}@{addr}:{port}?password={password}") + + print("Connection to SHV broker: ", url.to_url()) + return await SimpleClient.connect(url) + + +async def _get_parameter_value( + client: SimpleClient, mount_point: str, device_id: str, item: str, param_name: str +) -> SHVType | None: + call_url = f"{mount_point}/{device_id}/blocks/{param_name}/parameters/{item}" + try: + result = await client.call(call_url, "get") + return result + except RpcError as exc: + print("Can't read parameter ", param_name) + print(exc) + return None + + +async def _set_parameter_value( + client: SimpleClient, + mount_point: str, + device_id: str, + item: str, + param_name: str, + param_value: SHVType, +): + call_url = f"{mount_point}/{device_id}/blocks/{param_name}/parameters/{item}" + try: + return await client.call(call_url, "set", param_value) + except RpcError as e: + print("Can't set parameter ", param_name) + print(e) + + +async def _is_connected(client: SimpleClient) -> bool: + return client.client.connected + + +class ShvClient: + """Representation of SHV client connection to the broker.""" + + def __init__(self) -> None: + self.asyncio_loop = asyncio.new_event_loop() + self.asyncio_thread = Thread( + target=_start_background_loop, args=(self.asyncio_loop,), daemon=True + ) + self.client: SimpleClient | None = None + self.addr: str | None = None + self.port: str | None = None + self.user: str | None = None + self.password: str | None = None + self.device_id: str | None = None + self.mount_point: str | None = None + + self.asyncio_thread.start() + + def __del__(self) -> None: + self.asyncio_loop.stop() + + def _connect(self) -> None: + print("Connecting to broker...") + res = asyncio.run_coroutine_threadsafe( + _connect_client(self.user, self.addr, self.port, self.password), + self.asyncio_loop, + ) + try: + client = res.result() + except TimeoutError: + print("Connection to the broker timeouted!") + res.cancel() + except Exception as exc: + print(f"No connection to broker: {exc}") + else: + self.client = client + print("Connected to broker.") + + def _disconnect(self) -> None: + if self.client is None: + return + print("Disconnecting from broker...") + asyncio.run_coroutine_threadsafe( + _disconnect_client(self.client), self.asyncio_loop + ).result() + + self.client = None + + print("Disconnected from broker.") + + def _get_connection(self) -> SimpleClient: + if ( + self.client is None + or not asyncio.run_coroutine_threadsafe( + _is_connected(self.client), self.asyncio_loop + ).result() + ): + self._connect() + + return self.client + + def update_parameters_and_connect( + self, + addr: str, + port: str, + user: str, + password: str, + device_id: str, + mount_point: str, + ) -> None: + are_values_updated = ( + self.addr != addr + or self.port != port + or self.user != user + or self.password != password + or self.device_id != device_id + or self.mount_point != mount_point + ) + + self.addr = addr + self.port = port + self.user = user + self.password = password + self.device_id = device_id + self.mount_point = mount_point + + if are_values_updated: + self._disconnect() + + if self.client is None: + self._connect() + + def is_connected(self) -> bool: + if self.client is None: + return False + + return asyncio.run_coroutine_threadsafe( + _is_connected(self.client), self.asyncio_loop + ).result() + + def get_parameter_value(self, item: str, param_name: str) -> SHVType | None: + client = self._get_connection() + return asyncio.run_coroutine_threadsafe( + _get_parameter_value( + client, self.mount_point, self.device_id, item, param_name + ), + self.asyncio_loop, + ).result() + + def set_parameter_value(self, item: str, param_name: str, param_value: SHVType): + client = self._get_connection() + asyncio.run_coroutine_threadsafe( + _set_parameter_value( + client, self.mount_point, self.device_id, item, param_name, param_value + ), + self.asyncio_loop, + ).result() + + def disconnect(self): + self._disconnect() diff --git a/toolbox/supsisim/supsisim/shv/generator.py b/toolbox/supsisim/supsisim/shv/generator.py new file mode 100644 index 00000000..601d27ca --- /dev/null +++ b/toolbox/supsisim/supsisim/shv/generator.py @@ -0,0 +1,704 @@ +""" +SHV C tree generation. +""" + +from numpy import size +from os import environ +import copy +import typing + + +class ShvTreeGenerator: + def __init__(self, f: typing.IO, model: str, blocks) -> None: + self.f = f + self.model: str = model + self.blocks = blocks + self.blocks_cnt = size(blocks) + + self.blocks_ordered = [] + for n in range(0, self.blocks_cnt): + self.blocks_ordered.append(self.blocks[n].name) + self.blocks_ordered.sort() + + def generate_header(self) -> None: + if environ["SHV_USED"] == "True": + text: str = "#define CONF_SHV_USED 1\n\n" + else: + text = "#undef CONF_SHV_USED\n\n" + self.f.write(text) + + text = "#ifdef CONF_SHV_USED\n" + text += "#include \n" + text += "#include \n" + text += "#include \n" + text += "#include \n" + text += "#include \n\n" + self.f.write(text) + + if environ["SHV_TREE_TYPE"] == "GSA": + text = "#define CONF_SHV_TREE_TYPE 1\n" + text += "#undef CONF_SHV_TREE_STATIC\n\n" + elif environ["SHV_TREE_TYPE"] == "GSA_STATIC": + text = "#define CONF_SHV_TREE_TYPE 3\n" + text += "#define CONF_SHV_TREE_STATIC 1\n\n" + else: + text = "#define CONF_SHV_TREE_TYPE 0\n" + text += "#undef CONF_SHV_TREE_STATIC\n" + + text += "#endif /* CONF_SHV_USED */\n\n" + self.f.write(text) + + if environ["SHV_USED"] == "True": + self.f.write("/* SHV related function and structres */\n\n") + self.f.write("#ifdef CONF_SHV_USED\n") + self.f.write( + "shv_con_ctx_t *shv_tree_init(python_block_name_map * block_map, const shv_node_t *static_root, int mode);\n" + ) + self.f.write("void shv_tree_end(shv_con_ctx_t *ctx, int mode);\n\n") + + text = "python_block_name_map block_name_map_" + self.model + ";\n" + text += ( + "python_block_name_entry block_name_entry_" + + self.model + + "[" + + str(self.blocks_cnt) + + "];\n" + ) + text += "static shv_con_ctx_t *" + self.model + "_ctx;\n" + text += "#endif /* CONF_SHV_USED */\n\n" + self.f.write(text) + + def generate_tree(self) -> None: + self.f.write("#ifdef CONF_SHV_TREE_STATIC\n") + + has_system_inputs = False + has_system_outputs = False + has_blocks = False + + blks_names = [] + for i in range(0, self.blocks_cnt): + blks_names.append(self.blocks[i].name) + + for n in range(0, self.blocks_cnt): + has_real_pars = False + has_inputs = False + has_outputs = False + index = blks_names.index(self.blocks_ordered[n]) + + text = "" + if (self.blocks[index].fcn != "shv_input") and ( + self.blocks[index].fcn != "shv_output" + ): + has_blocks = True + if size(self.blocks[index].realPar) != 0: + has_real_pars = True + + real_par_names = [] + + if size(self.blocks[index].realPar) == size( + self.blocks[index].real_par_names + ): + for i in range(0, size(self.blocks[index].realPar)): + real_par_names.append(self.blocks[index].real_par_names[i]) + else: + for i in range(0, size(self.blocks[index].realPar)): + real_par_names.append("double" + str(i)) + + real_par_names_ordered = copy.deepcopy(real_par_names) + real_par_names_ordered.sort() + + for i in range(0, size(self.blocks[index].realPar)): + indexPar = real_par_names.index(real_par_names_ordered[i]) + text += ( + "const shv_node_typed_val_t shv_node_typed_val_blk" + + str(n) + + "_par" + + str(i) + + " = {\n" + + ' .shv_node = {.name = "' + + str(real_par_names[indexPar]) + + '",\n' + + " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_double_dmap),\n" + + " },\n" + + " .val_ptr = &realPar_" + + str(index) + + "[" + + str(indexPar) + + "],\n" + + ' .type_name = "double",\n};\n\n' + ) + self.f.write(text) + text = ( + "const shv_node_typed_val_t *const shv_node_typed_val_blk" + + str(n) + + "_pars" + + "[] = {\n" + ) + for i in range(0, size(self.blocks[index].realPar)): + text += ( + " &shv_node_typed_val_blk" + + str(n) + + "_par" + + str(i) + + ",\n" + ) + + text += "};\n\n" + self.f.write(text) + + text = ( + "const shv_node_t shv_node_blk" + + str(n) + + "_par = {\n" + + ' .name = "parameters",\n' + + " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_blk_dmap),\n" + + " .children = {.mode = CONF_SHV_TREE_TYPE,\n" + ) + if has_real_pars: + text += ( + " .list = {.gsa = {.root = {\n" + + " .items = (void **)shv_node_typed_val_blk" + + str(n) + + "_pars,\n" + + " .count = sizeof(shv_node_typed_val_blk" + + str(n) + + "_pars)/sizeof(shv_node_typed_val_blk" + + str(n) + + "_pars[0]),\n" + + " .alloc_count = 0,}\n" + + "}}" + ) + text += "}};\n\n" + self.f.write(text) + + if size(self.blocks[index].pin) != 0: + has_inputs = True + text = "" + for i in range(0, size(self.blocks[index].pin)): + text += ( + "const shv_node_typed_val_t shv_node_typed_val_blk" + + str(n) + + "_in" + + str(i) + + " = {\n" + + ' .shv_node = {.name = "input' + + str(i) + + '",\n' + + " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_double_read_only_dmap),\n" + + " },\n" + + " .val_ptr = Node_" + + str(self.blocks[index].pin[i]) + + ",\n" + + ' .type_name = "double",\n};\n\n' + ) + self.f.write(text) + text = ( + "const shv_node_typed_val_t *const shv_node_typed_val_blk" + + str(n) + + "_ins" + + "[] = {\n" + ) + for i in range(0, size(self.blocks[index].pin)): + text += ( + " &shv_node_typed_val_blk" + + str(n) + + "_in" + + str(i) + + ",\n" + ) + text += "};\n\n" + self.f.write(text) + + text = ( + "const shv_node_t shv_node_blk" + + str(n) + + "_in = {\n" + + ' .name = "inputs",\n' + + " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_blk_dmap),\n" + + " .children = {.mode = CONF_SHV_TREE_TYPE,\n" + ) + if has_inputs: + text += ( + " .list = {.gsa = {.root = {\n" + + " .items = (void **)shv_node_typed_val_blk" + + str(n) + + "_ins,\n" + + " .count = sizeof(shv_node_typed_val_blk" + + str(n) + + "_ins)/sizeof(shv_node_typed_val_blk" + + str(n) + + "_ins[0]),\n" + + " .alloc_count = 0,}\n" + + "}}" + ) + text += "}};\n\n" + self.f.write(text) + + if size(self.blocks[index].pout) != 0: + has_outputs = True + text = "" + for i in range(0, size(self.blocks[index].pout)): + text += ( + "const shv_node_typed_val_t shv_node_typed_val_blk" + + str(n) + + "_out" + + str(i) + + " = {\n" + + ' .shv_node = {.name = "output' + + str(i) + + '",\n' + + " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_double_read_only_dmap),\n" + + " },\n" + + " .val_ptr = Node_" + + str(self.blocks[index].pout[i]) + + ",\n" + + ' .type_name = "double",\n};\n\n' + ) + self.f.write(text) + text = ( + "const shv_node_typed_val_t *const shv_node_typed_val_blk" + + str(n) + + "_outs" + + "[] = {\n" + ) + for i in range(0, size(self.blocks[index].pout)): + text += ( + " &shv_node_typed_val_blk" + + str(n) + + "_out" + + str(i) + + ",\n" + ) + text += "};\n\n" + self.f.write(text) + + text = ( + "const shv_node_t shv_node_blk" + + str(n) + + "_out = {\n" + + ' .name = "outputs",\n' + + " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_blk_dmap),\n" + + " .children = {.mode = CONF_SHV_TREE_TYPE,\n" + ) + if has_outputs: + text += ( + " .list = {.gsa = {.root = {\n" + + " .items = (void **)shv_node_typed_val_blk" + + str(n) + + "_outs,\n" + + " .count = sizeof(shv_node_typed_val_blk" + + str(n) + + "_outs)/sizeof(shv_node_typed_val_blk" + + str(n) + + "_outs[0]),\n" + + " .alloc_count = 0,}\n" + + "}}" + ) + text += "}};\n\n" + self.f.write(text) + + text = ( + "const shv_node_t *const shv_node_blk" + + str(n) + + "_items" + + "[] = {\n" + ) + text += " &shv_node_blk" + str(n) + "_in,\n" + text += " &shv_node_blk" + str(n) + "_out,\n" + text += " &shv_node_blk" + str(n) + "_par\n" + text += "};\n\n" + self.f.write(text) + + text = ( + "const shv_node_t shv_node_blk" + + str(n) + + " = {\n" + + ' .name = "' + + str(self.blocks[index].name) + + '",\n' + + " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_blk_dmap),\n" + + " .children = {.mode = CONF_SHV_TREE_TYPE,\n" + + " .list = {.gsa = {.root = {\n" + + " .items = (void **)shv_node_blk" + + str(n) + + "_items,\n" + + " .count = sizeof(shv_node_blk" + + str(n) + + "_items)/sizeof(shv_node_blk" + + str(n) + + "_items[0]),\n" + + " .alloc_count = 0,}\n" + + "}}}};\n\n" + ) + self.f.write(text) + + text = "" + if self.blocks[index].fcn == "shv_input": + has_system_inputs = True + # we have editable outputs (SHV input block) + for i in range(0, size(self.blocks[index].pout)): + text += ( + "const shv_node_typed_val_t shv_node_typed_val_blk" + + str(n) + + "_sysIn" + + str(i) + + " = {\n" + + ' .shv_node = {.name = "input' + + str(i) + + '",\n' + + " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_double_dmap),\n" + + " },\n" + + " .val_ptr = Node_" + + str(self.blocks[index].pout[i]) + + ",\n" + + ' .type_name = "double",\n};\n\n' + ) + self.f.write(text) + text = ( + "const shv_node_typed_val_t *const shv_node_typed_val_blk" + + str(n) + + "_sysIns" + + "[] = {\n" + ) + for i in range(0, size(self.blocks[index].pout)): + text += ( + " &shv_node_typed_val_blk" + str(n) + "_sysIn" + str(i) + ",\n" + ) + + text += "};\n\n" + self.f.write(text) + + text = ( + "const shv_node_t shv_node_blk" + + str(n) + + "_sysIns = {\n" + + ' .name = "' + + str(self.blocks[index].name) + + '",\n' + + " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_blk_dmap),\n" + + " .children = {.mode = CONF_SHV_TREE_TYPE,\n" + + " .list = {.gsa = {.root = {\n" + + " .items = (void **)shv_node_typed_val_blk" + + str(n) + + "_sysIns,\n" + + " .count = sizeof(shv_node_typed_val_blk" + + str(n) + + "_sysIns)/sizeof(shv_node_typed_val_blk" + + str(n) + + "_sysIns[0]),\n" + + " .alloc_count = 0,}\n" + + "}}}};\n\n" + ) + self.f.write(text) + + if self.blocks[index].fcn == "shv_output": + has_system_outputs = True + # we have editable inputs (SHV output block) + for i in range(0, size(self.blocks[index].pin)): + text += ( + "const shv_node_typed_val_t shv_node_typed_val_blk" + + str(n) + + "_sysOut" + + str(i) + + " = {\n" + + ' .shv_node = {.name = "output' + + str(i) + + '",\n' + + " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_double_read_only_dmap),\n" + + " },\n" + + " .val_ptr = Node_" + + str(self.blocks[index].pin[i]) + + ",\n" + + ' .type_name = "double",\n};\n\n' + ) + self.f.write(text) + text = ( + "const shv_node_typed_val_t *const shv_node_typed_val_blk" + + str(n) + + "_sysOuts" + + "[] = {\n" + ) + for i in range(0, size(self.blocks[index].pin)): + text += ( + " &shv_node_typed_val_blk" + + str(n) + + "_sysOut" + + str(i) + + ",\n" + ) + + text += "};\n\n" + self.f.write(text) + + text = ( + "const shv_node_t shv_node_blk" + + str(n) + + "_sysOuts = {\n" + + ' .name = "' + + str(self.blocks[index].name) + + '",\n' + + " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_blk_dmap),\n" + + " .children = {.mode = CONF_SHV_TREE_TYPE,\n" + + " .list = {.gsa = {.root = {\n" + + " .items = (void **)shv_node_typed_val_blk" + + str(n) + + "_sysOuts,\n" + + " .count = sizeof(shv_node_typed_val_blk" + + str(n) + + "_sysOuts)/sizeof(shv_node_typed_val_blk" + + str(n) + + "_sysOuts[0]),\n" + + " .alloc_count = 0,}\n" + + "}}}};\n\n" + ) + self.f.write(text) + + if has_blocks: + text = "const shv_node_t *const shv_node_blks_list[] = {\n" + for n in range(0, self.blocks_cnt): + index = blks_names.index(self.blocks_ordered[n]) + if (self.blocks[index].fcn != "shv_input") and ( + self.blocks[index].fcn != "shv_output" + ): + text += " &shv_node_blk" + str(n) + ",\n" + text += "};\n\n" + self.f.write(text) + + text = ( + "const shv_node_t shv_node_blks = {\n" + + ' .name = "blocks",\n' + + " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_root_dmap),\n" + + " .children = {.mode = CONF_SHV_TREE_TYPE,\n" + ) + if has_blocks: + text += ( + " .list = {.gsa = {.root = {\n" + + " .items = (void **)shv_node_blks_list,\n" + + " .count = sizeof(shv_node_blks_list)/sizeof(shv_node_blks_list[0]),\n" + + " .alloc_count = 0,}\n" + + "}}" + ) + text += "}};\n\n" + self.f.write(text) + + if has_system_inputs: + text = "const shv_node_t *const shv_node_blks_inputs[] = {\n" + for n in range(0, self.blocks_cnt): + index = blks_names.index(self.blocks_ordered[n]) + if (size(self.blocks[index].pout) != 0) and ( + self.blocks[index].fcn == "shv_input" + ): + text += " &shv_node_blk" + str(n) + "_sysIns,\n" + text += "};\n\n" + self.f.write(text) + + text = ( + "const shv_node_t shv_node_inputs = {\n" + + ' .name = "inputs",\n' + + " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_root_dmap),\n" + + " .children = {.mode = CONF_SHV_TREE_TYPE,\n" + ) + if has_system_inputs: + text += ( + " .list = {.gsa = {.root = {\n" + + " .items = (void **)shv_node_blks_inputs,\n" + + " .count = sizeof(shv_node_blks_inputs)/sizeof(shv_node_blks_inputs[0]),\n" + + " .alloc_count = 0,}\n" + + "}}" + ) + text += "}};\n\n" + self.f.write(text) + + if has_system_outputs: + text = "const shv_node_t *const shv_node_blks_outputs[] = {\n" + for n in range(0, self.blocks_cnt): + index = blks_names.index(self.blocks_ordered[n]) + if (size(self.blocks[index].pin) != 0) and ( + self.blocks[index].fcn == "shv_output" + ): + text += " &shv_node_blk" + str(n) + "_sysOuts,\n" + text += "};\n\n" + self.f.write(text) + + text = ( + "const shv_node_t shv_node_outputs = {\n" + + ' .name = "outputs",\n' + + " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_root_dmap),\n" + + " .children = {.mode = CONF_SHV_TREE_TYPE,\n" + ) + if has_system_outputs: + text += ( + " .list = {.gsa = {.root = {\n" + + " .items = (void **)shv_node_blks_outputs,\n" + + " .count = sizeof(shv_node_blks_outputs)/sizeof(shv_node_blks_outputs[0]),\n" + + " .alloc_count = 0,}\n" + + "}}" + ) + text += "}};\n\n" + self.f.write(text) + + text = ( + "const shv_node_t *const shv_tree_root_items[] = {\n" + + " &shv_node_blks,\n" + + " &shv_node_inputs,\n" + + " &shv_node_outputs,\n};\n\n" + ) + self.f.write(text) + + text = ( + "const shv_node_t shv_tree_root = {\n" + + " .dir = UL_CAST_UNQ1(shv_dmap_t *, &shv_root_dmap),\n" + + " .children = {.mode = CONF_SHV_TREE_TYPE,\n" + + " .list = {.gsa = {.root = {\n" + + " .items = (void **)shv_tree_root_items,\n" + + " .count = sizeof(shv_tree_root_items)/sizeof(shv_tree_root_items[0]),\n" + + " .alloc_count = 0,}\n" + + "}}}};\n\n" + ) + self.f.write(text) + + self.f.write("#endif /* CONF_SHV_TREE_STATIC */") + + def generate_code(self) -> None: + text = "#ifdef CONF_SHV_USED\n" + text += ' setenv("SHV_BROKER_IP", "' + environ["SHV_BROKER_IP"] + '", 0);\n' + text += ( + ' setenv("SHV_BROKER_PORT", "' + environ["SHV_BROKER_PORT"] + '", 0);\n' + ) + text += ( + ' setenv("SHV_BROKER_USER", "' + environ["SHV_BROKER_USER"] + '", 0);\n' + ) + text += ( + ' setenv("SHV_BROKER_PASSWORD", "' + + environ["SHV_BROKER_PASSWORD"] + + '", 0);\n' + ) + text += ( + ' setenv("SHV_BROKER_DEV_ID", "' + + environ["SHV_BROKER_DEV_ID"] + + '", 0);\n' + ) + text += ( + ' setenv("SHV_BROKER_MOUNT", "' + + environ["SHV_BROKER_MOUNT"] + + '", 0);\n\n' + ) + self.f.write(text) + + self.f.write("/* SHV structures definition */\n\n") + + blks_names = [] + for i in range(0, self.blocks_cnt): + blks_names.append(self.blocks[i].name) + + text = "" + for n in range(0, self.blocks_cnt): + index = blks_names.index(self.blocks_ordered[n]) + text += ( + " block_name_entry_" + + self.model + + "[" + + str(n) + + '].block_name = "' + + self.blocks_ordered[n] + + '";\n' + ) + text += ( + " block_name_entry_" + + self.model + + "[" + + str(n) + + "].block_idx = " + + str(index) + + ";\n" + ) + if self.blocks[index].fcn == "shv_input": + text += ( + " block_name_entry_" + + self.model + + "[" + + str(n) + + "].system_inputs = " + + str(1) + + ";\n" + ) + else: + text += ( + " block_name_entry_" + + self.model + + "[" + + str(n) + + "].system_inputs = " + + str(0) + + ";\n" + ) + if self.blocks[index].fcn == "shv_output": + text += ( + " block_name_entry_" + + self.model + + "[" + + str(n) + + "].system_outputs = " + + str(1) + + ";\n" + ) + else: + text += ( + " block_name_entry_" + + self.model + + "[" + + str(n) + + "].system_outputs = " + + str(0) + + ";\n" + ) + + text += "\n" + self.f.write(text) + + text = ( + " block_name_map_" + + self.model + + ".blocks_count = " + + str(self.blocks_cnt) + + ";\n" + ) + text += ( + " block_name_map_" + + self.model + + ".blocks = " + + "block_name_entry_" + + self.model + + ";\n" + ) + text += ( + " block_name_map_" + + self.model + + ".block_structure = block_" + + self.model + + ";\n\n" + ) + self.f.write(text) + + self.f.write("/* Call shv_tree_init() to initialize SHV tree */\n\n") + + if environ["SHV_TREE_TYPE"] != "GSA_STATIC": + text = " const shv_node_t shv_tree_root = {};\n\n" + self.f.write(text) + + text = ( + " " + + self.model + + "_ctx = shv_tree_init(&block_name_map_" + + self.model + + ", &shv_tree_root, CONF_SHV_TREE_TYPE);\n\n" + ) + self.f.write(text) + + self.f.write("#endif /* CONF_SHV_USED */\n\n") + + def generate_end(self) -> None: + text = "#ifdef CONF_SHV_USED\n" + text += " shv_tree_end(" + self.model + "_ctx, CONF_SHV_TREE_TYPE);\n" + text += "#endif /* CONF_SHV_USED */\n\n" + self.f.write(text)