synchronousTool.py 51.3 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# (C) Semantix Information Technologies.
#
# Semantix Information Technologies is licensing the code of the
# Data Modelling Tools (DMT) in the following dual-license mode:
#
# Commercial Developer License:
#       The DMT Commercial Developer License is the suggested version
# to use for the development of proprietary and/or commercial software.
# This version is for developers/companies who do not want to comply
# with the terms of the GNU Lesser General Public License version 2.1.
#
# GNU LGPL v. 2.1:
#       This version of DMT is the one to use for the development of
# applications, when you are willing to comply with the terms of the
# GNU Lesser General Public License version 2.1.
#
# Note that in both cases, there are no charges (royalties) for the
# generated code.
#
20
'''
21
22
23
24
25
26
Base class for all synchronous tools
'''

import re
import os

27
from typing import IO, Any, Generic, TypeVar  # NOQA pylint: disable=unused-import
28

29
from ..commonPy.utility import panic, inform, panicWithCallStack
30
from ..commonPy.aadlAST import InParam, OutParam, InOutParam, ApLevelContainer, Param
31
from ..commonPy.recursiveMapper import RecursiveMapperGeneric
32
33
from ..commonPy.asnAST import AsnNode
from ..commonPy.asnParser import AST_Lookup, AST_Leaftypes
34
35


36
37
38
TSource = TypeVar('TSource')
TDestin = TypeVar('TDestin')

Tiago Jorge's avatar
Tiago Jorge committed
39
brave_seen = {}
40
# Add suffix to generated FPGA device driver's (<PI name>_<Language>.vhdl.c) functions to avoid multiple definition errors (conflict with "vm_if")
41
fpgaSuffix = ''
42
43
44
# Add a different suffix to the dispatcher C function (part of device driver)
# Dispatcher <Function Block name>_<PI name><dispatcherSuffix> will delegate to one or the other side (SW or HW)
# If delegation is to HW, then <Function Block name>_<PI name><fpgaSuffix> will be called
45
dispatcherSuffix = "_Brave_Dispatch"
46
47
48
# FPGA/HW device driver (<PI name>_<Language>.vhdl.c) is being generated (also) when Function Block will exist both as SW and HW, that is, when
# 1) language defined is C or Simulink but on the autogen pass is "seen" as VHDL (so that respective B-mapper is invoked),
# and 2) there are FPGA configurations defined (default is False)
49
genHwDevDrv = False
50
51

class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
52
53
54
55

    ##############################################
    # Parts to override for each synchronous tool

56
    def Version(self) -> None:  # pylint: disable=no-self-use
57
58
        panicWithCallStack("Method undefined in a SynchronousToolGlueGenerator...")  # pragma: no cover

59
    def FromToolToASN1SCC(self) -> RecursiveMapperGeneric:  # pylint: disable=no-self-use
60
61
        panicWithCallStack("Method undefined in a SynchronousToolGlueGenerator...")  # pragma: no cover

62
    def FromToolToOSS(self) -> RecursiveMapperGeneric:  # pylint: disable=no-self-use
63
64
        panicWithCallStack("Method undefined in a SynchronousToolGlueGenerator...")  # pragma: no cover

65
    def FromASN1SCCtoTool(self) -> RecursiveMapperGeneric:  # pylint: disable=no-self-use
66
67
        panicWithCallStack("Method undefined in a SynchronousToolGlueGenerator...")  # pragma: no cover

68
    def FromOSStoTool(self) -> RecursiveMapperGeneric:  # pylint: disable=no-self-use
69
70
        panicWithCallStack("Method undefined in a SynchronousToolGlueGenerator...")  # pragma: no cover

71
    def HeadersOnStartup(self, unused_modelingLanguage: str, unused_asnFile: str, unused_subProgram: ApLevelContainer, unused_subProgramImplementation: str, unused_outputDir: str, unused_maybeFVname: str) -> None:  # pylint: disable=no-self-use
72
73
        panicWithCallStack("Method undefined in a SynchronousToolGlueGenerator...")  # pragma: no cover

74
    def SourceVar(self, unused_nodeTypename: str, unused_encoding: str, unused_node: AsnNode, unused_subProgram: ApLevelContainer, unused_subProgramImplementation: str, unused_param: Param, unused_leafTypeDict: AST_Leaftypes, unused_names: AST_Lookup) -> TSource:  # pylint: disable=no-self-use
75
76
        panicWithCallStack("Method undefined in a SynchronousToolGlueGenerator...")  # pragma: no cover

77
    def TargetVar(self, unused_nodeTypename: str, unused_encoding: str, unused_node: AsnNode, unused_subProgram: ApLevelContainer, unused_subProgramImplementation: str, unused_param: Param, unused_leafTypeDict: AST_Leaftypes, unused_names: AST_Lookup) -> TDestin:  # pylint: disable=no-self-use
78
79
        panicWithCallStack("Method undefined in a SynchronousToolGlueGenerator...")  # pragma: no cover

80
    def InitializeBlock(self, unused_modelingLanguage: str, unused_asnFile: str, unused_sp: ApLevelContainer, unused_subProgramImplementation: str, unused_maybeFVname: str) -> None:  # pylint: disable=no-self-use
81
82
        panicWithCallStack("Method undefined in a SynchronousToolGlueGenerator...")  # pragma: no cover

83
    def ExecuteBlock(self, unused_modelingLanguage: str, unused_asnFile: str, unused_sp: ApLevelContainer, unused_subProgramImplementation: str, unused_maybeFVname: str) -> None:  # pylint: disable=no-self-use
84
85
86
87
88
        panicWithCallStack("Method undefined in a SynchronousToolGlueGenerator...")  # pragma: no cover

    ########################################################
    # Parts to possibly override for each synchronous tool

89
    # noinspection PyMethodMayBeStatic
90
    def CleanNameAsToolWants(self, name: str) -> str:  # pylint: disable=no-self-use
91
92
        return re.sub(r'[^a-zA-Z0-9_]', '_', name)

93
    # noinspection PyMethodMayBeStatic
94
    def CleanNameAsADAWants(self, name: str) -> str:  # pylint: disable=no-self-use
95
96
97
98
99
        return re.sub(r'[^a-zA-Z0-9_]', '_', name)

    ##########################################
    # Common parts for all synchronous tools

100
    def __init__(self) -> None:
101
        # The files written to
102
103
104
105
        self.C_HeaderFile = None  # type: IO[Any]
        self.C_SourceFile = None  # type: IO[Any]
        self.ADA_HeaderFile = None  # type: IO[Any]
        self.ADA_SourceFile = None  # type: IO[Any]
106
107
        self.asn_name = ""
        self.supportedEncodings = ['native', 'uper', 'acn']
108
109
        self.dir = None  # type: str
        self.useOSS = None  # type: bool
110

111
112
113
114
115
116
117
118
    def OnStartup(self,
                  modelingLanguage: str,
                  asnFile: str,
                  subProgram: ApLevelContainer,
                  subProgramImplementation: str,
                  outputDir: str,
                  maybeFVname: str,
                  useOSS: bool) -> None:
119
120
121
        # FPGA/HW device driver is being generated (also) when Function Block will exist both as SW and HW, that is, when
        # 1) language defined is C or Simulink but on this autogen pass is "seen" as VHDL (so that respective B-mapper is invoked),
        # and 2) there are FPGA configurations defined
122
        global genHwDevDrv
123
        # Add suffix to generated FPGA device driver's functions to avoid multiple definition errors (conflict with "vm_if")
124
125
126
127
128
        global fpgaSuffix
        genHwDevDrv = subProgram._fpgaConfigurations is not '' and ((subProgramImplementation.lower() == "c" or subProgramImplementation.lower() == "simulink") and modelingLanguage == "vhdl");
        if genHwDevDrv:
            fpgaSuffix = "_Brave_Fpga"
        else:
129
            # To avoid code duplication, use suffix anyway but as an empty string when not to be applied
130
131
            fpgaSuffix = ''
        
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
        if modelingLanguage == "QGenAda":
            self.dir = outputDir
            self.useOSS = useOSS

            outputADAsourceFilename = self.CleanNameAsADAWants(subProgram._id + "_" + subProgramImplementation) + "_wrapper.adb"
            outputADAsourceFilename = outputADAsourceFilename.lower()
            outputADAheaderFilename = self.CleanNameAsADAWants(subProgram._id + "_" + subProgramImplementation) + "_wrapper.ads"
            outputADAheaderFilename = outputADAheaderFilename.lower()

            inform(str(self.__class__) + ": Creating file '%s'...", outputADAheaderFilename)
            self.ADA_HeaderFile = open(outputDir + outputADAheaderFilename, 'w')

            inform(str(self.__class__) + ": Creating file '%s'...", outputADAsourceFilename)
            self.ADA_SourceFile = open(outputDir + outputADAsourceFilename, 'w')

            self.asn_name = os.path.basename(os.path.splitext(asnFile)[0])

            self.ADA_HeaderFile.write('with taste_dataview;\n')
            self.ADA_HeaderFile.write('use taste_dataview;\n')
            self.ADA_HeaderFile.write('with %s_types;\n' % self.CleanNameAsADAWants(subProgram._id))
            self.ADA_HeaderFile.write('use %s_types;\n\n' % self.CleanNameAsADAWants(subProgram._id))
            self.ADA_HeaderFile.write(
                'package %s is\n\n' %
                self.CleanNameAsADAWants(subProgram._id + "_" + subProgramImplementation + "_wrapper"))

            self.ADA_SourceFile.write('with %s;\n' % self.CleanNameAsADAWants(subProgram._id))
            self.ADA_SourceFile.write('with %s_types;\n' % self.CleanNameAsADAWants(subProgram._id))
            self.ADA_SourceFile.write('use %s_types;\n\n' % self.CleanNameAsADAWants(subProgram._id))
            self.ADA_SourceFile.write(
                'package body %s is\n\n' %
                self.CleanNameAsADAWants(subProgram._id + "_" + subProgramImplementation + "_wrapper"))
        else:
            self.dir = outputDir
            self.useOSS = useOSS

            outputCheaderFilename = \
                self.CleanNameAsToolWants(subProgram._id + "_" + subProgramImplementation) + "." + self.CleanNameAsToolWants(modelingLanguage) + ".h"
            outputCsourceFilename = \
                self.CleanNameAsToolWants(subProgram._id + "_" + subProgramImplementation) + "." + self.CleanNameAsToolWants(modelingLanguage) + ".c"
            outputADAsourceFilename = self.CleanNameAsADAWants(subProgram._id + "_" + subProgramImplementation) + ".adb"
            outputADAsourceFilename = outputADAsourceFilename.lower()
            outputADAheaderFilename = self.CleanNameAsADAWants(subProgram._id + "_" + subProgramImplementation) + ".ads"
            outputADAheaderFilename = outputADAheaderFilename.lower()

            inform(str(self.__class__) + ": Creating file '%s'...", outputCheaderFilename)
            self.C_HeaderFile = open(outputDir + outputCheaderFilename, 'w')

            inform(str(self.__class__) + ": Creating file '%s'...", outputCsourceFilename)
            self.C_SourceFile = open(outputDir + outputCsourceFilename, 'w')

            inform(str(self.__class__) + ": Creating file '%s'...", outputADAheaderFilename)
            self.ADA_HeaderFile = open(outputDir + outputADAheaderFilename, 'w')

            inform(str(self.__class__) + ": Creating file '%s'...", outputADAsourceFilename)
            self.ADA_SourceFile = open(outputDir + outputADAsourceFilename, 'w')

            self.asn_name = os.path.basename(os.path.splitext(asnFile)[0])

            ID = modelingLanguage.upper() + "_" + \
                os.path.basename(asnFile).replace(".", "").upper() + "_" + \
                self.CleanNameAsToolWants(subProgram._id + "_" + subProgramImplementation).upper()
            ID = re.sub(r'[^A-Za-z0-9_]', '_', ID).upper()
            self.C_HeaderFile.write("#ifndef __%s_H__\n" % ID)
            self.C_HeaderFile.write("#define __%s_H__\n\n" % ID)
            self.C_HeaderFile.write("#include <stdlib.h> /* for size_t */\n")
            self.C_HeaderFile.write("\n")

199
            self.C_SourceFile.write("#ifdef __unix__\n")
200
201
202
            self.C_SourceFile.write("#include <stdio.h>\n")
            self.C_SourceFile.write("#include <string.h>\n\n")
            self.C_SourceFile.write("#include <assert.h>\n\n")
203
            self.C_SourceFile.write("#endif\n")
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

            self.C_SourceFile.write("#include \"%s\"\n" % outputCheaderFilename)

            self.HeadersOnStartup(modelingLanguage, asnFile, subProgram, subProgramImplementation, outputDir, maybeFVname)

            self.ADA_HeaderFile.write('with Interfaces.C.Extensions;\n')
            self.ADA_HeaderFile.write('use Interfaces.C.Extensions;\n\n')
            self.ADA_HeaderFile.write(
                'package %s is\n\n' %
                self.CleanNameAsADAWants(subProgram._id + "_" + subProgramImplementation))

            self.ADA_SourceFile.write('with Interfaces.C.Extensions;\n')
            self.ADA_SourceFile.write('use Interfaces.C.Extensions;\n\n')
            self.ADA_SourceFile.write(
                'package body %s is\n\n' %
                self.CleanNameAsADAWants(subProgram._id + "_" + subProgramImplementation))

221
222
223
224
225
226
227
228
229
    def Encoder(self,
                nodeTypename: str,
                encoding: str,
                node: AsnNode,
                subProgram: ApLevelContainer,
                subProgramImplementation: str,
                param: Param,
                leafTypeDict: AST_Leaftypes,
                names: AST_Lookup) -> None:
230
231
        global fpgaSuffix
        
232
        if encoding.lower() not in self.supportedEncodings:
233
234
            panic(str(self.__class__) + ": in (%s), encoding can be one of %s (not '%s')" % (  # pragma: no cover
                subProgram._id + "." + subProgramImplementation, self.supportedEncodings, encoding))  # pragma: no cover
235
236

        tmpSpName = "Convert_From_%s_To_%s_In_%s_%s" % \
237
238
239
240
            (self.CleanNameAsADAWants(nodeTypename),
             encoding.lower(),
             self.CleanNameAsADAWants(subProgram._id + "_" + subProgramImplementation),
             self.CleanNameAsADAWants(param._id))
241
242
243
244
245
246
247
248
249
250
251

        srcVar = self.SourceVar(nodeTypename, encoding, node, subProgram, subProgramImplementation, param, leafTypeDict, names)

        if subProgramImplementation == "QGenAda":
            self.ADA_HeaderFile.write(
                "    procedure Ada_%s(QGen_OUT : in %s; T_OUT : out %s);\n" %
                (tmpSpName, self.CleanNameAsToolWants(nodeTypename), "asn1Scc" + self.CleanNameAsToolWants(nodeTypename)))
            self.ADA_SourceFile.write(
                "    procedure Ada_%s(QGen_OUT : in %s; T_OUT : out %s) is\n" %
                (tmpSpName, self.CleanNameAsToolWants(nodeTypename), "asn1Scc" + self.CleanNameAsToolWants(nodeTypename)))
            self.ADA_SourceFile.write('begin\n')
252

253
            toolToAsn1 = self.FromToolToASN1SCC()
254
            lines = toolToAsn1.Map(
255
256
257
258
                "QGen_OUT",
                "T_OUT",
                node,
                leafTypeDict,
259
                names) if toolToAsn1 else []
260

261
            lines = ["        " + x for x in lines]
262
            self.ADA_SourceFile.write("".join(lines))
263

264
265
266
267
            self.ADA_SourceFile.write(
                "    end Ada_%s;\n\n" % tmpSpName)
        else:
            self.C_HeaderFile.write(
268
                "int %s%s(void *pBuffer, size_t iMaxBufferSize);\n" % (tmpSpName, fpgaSuffix))
269
270
271
272
273
274
275
276
277
278
279
280
281
282
            self.ADA_HeaderFile.write(
                "procedure Ada_%s(pBuffer : in Interfaces.C.char_array; iMaxBufferSize : in Integer; bytesWritten : out Integer);\n" % tmpSpName)
            self.ADA_SourceFile.write(
                "procedure Ada_%s(pBuffer : in Interfaces.C.char_array; iMaxBufferSize : in Integer; bytesWritten : out Integer) is\n" % tmpSpName)
            self.ADA_SourceFile.write(
                "    function C_%s(pBuffer : Interfaces.C.char_array; iMaxBufferSize : Integer) return Integer;\n" % tmpSpName)
            self.ADA_SourceFile.write(
                '    pragma Import(C, C_%s, "%s");\n' % (tmpSpName, tmpSpName))
            self.ADA_SourceFile.write(
                'begin\n'
                '    bytesWritten := C_%s(pBuffer, iMaxBufferSize);\n' % tmpSpName)
            self.ADA_SourceFile.write(
                "end Ada_%s;\n\n" % tmpSpName)
            self.C_SourceFile.write(
283
                "int %s%s(void *pBuffer, size_t iMaxBufferSize)\n{\n" % (tmpSpName, fpgaSuffix))
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307

            if self.useOSS and encoding.lower() == "uper":
                self.C_SourceFile.write(
                    "    STATIC OSS_%s var_%s;\n" %
                    (self.CleanNameAsToolWants(nodeTypename), self.CleanNameAsToolWants(nodeTypename)))
            else:
                self.C_SourceFile.write(
                    "    STATIC asn1Scc%s var_%s;\n" %
                    (self.CleanNameAsToolWants(nodeTypename), self.CleanNameAsToolWants(nodeTypename)))

            if encoding.lower() in ["uper", "acn"]:
                if self.useOSS:
                    self.C_SourceFile.write("    STATIC OssBuf strm;\n")
                else:
                    self.C_SourceFile.write("    int errorCode;\n")
                    self.C_SourceFile.write("    STATIC BitStream strm;\n\n")
                    # setup the asn1c encoder
                    self.C_SourceFile.write("    BitStream_Init(&strm, pBuffer, iMaxBufferSize);\n")

            # Write the mapping code for the message
            if self.useOSS and encoding.lower() == "uper":
                toolToAsn1 = self.FromToolToOSS()
            else:
                toolToAsn1 = self.FromToolToASN1SCC()
308
            lines = toolToAsn1.Map(
309
310
311
312
                srcVar,
                "var_" + self.CleanNameAsToolWants(nodeTypename),
                node,
                leafTypeDict,
313
                names) if toolToAsn1 else []
314

315
            lines = ["    " + x for x in lines]
316
317
318
319
320
321
322
323
324
            self.C_SourceFile.write("".join(lines))

            if self.useOSS and encoding.lower() == "uper":
                # setup the OSS encoder
                self.C_SourceFile.write("\n    strm.value = NULL;\n")
                self.C_SourceFile.write("    strm.length = 0;\n")
                self.C_SourceFile.write(
                    "    if (ossEncode(g_world, OSS_%s_PDU, &var_%s, &strm) != 0) {\n" %
                    (self.CleanNameAsToolWants(nodeTypename), self.CleanNameAsToolWants(nodeTypename)))
325
                self.C_SourceFile.write("#ifdef __unix__\n")
326
                self.C_SourceFile.write(
327
                    '        fprintf(stderr, "Could not encode %s (at %%s, %%d), errorMessage was %%s\\n", __FILE__, __LINE__, ossGetErrMsg(g_world));\n' % nodeTypename)
328
                self.C_SourceFile.write("#endif\n")
329
330
331
332
333
334
335
336
337
338
339
340
                self.C_SourceFile.write("        return -1;\n")
                self.C_SourceFile.write("    } else {\n")
                self.C_SourceFile.write("        assert(strm.length <= iMaxBufferSize);\n")
                self.C_SourceFile.write("        memcpy(pBuffer, strm.value, strm.length);\n")
                self.C_SourceFile.write("        ossFreeBuf(g_world, strm.value);\n")
                self.C_SourceFile.write("        return strm.length;\n")
                self.C_SourceFile.write("    }\n")
                self.C_SourceFile.write("}\n\n")
            elif encoding.lower() in ["uper", "acn"]:
                self.C_SourceFile.write(
                    "    if (asn1Scc%s_%sEncode(&var_%s, &strm, &errorCode, TRUE) == FALSE) {\n" %
                    (self.CleanNameAsToolWants(nodeTypename),
341
                     "ACN_" if encoding.lower() == "acn" else "",
342
                     self.CleanNameAsToolWants(nodeTypename)))
343
                self.C_SourceFile.write("#ifdef __unix__\n")
344
                self.C_SourceFile.write(
345
                    '        fprintf(stderr, "Could not encode %s (at %%s, %%d), errorCode was %%d\\n", __FILE__, __LINE__, errorCode);\n' % nodeTypename)
346
                self.C_SourceFile.write("#endif\n")
347
348
349
350
351
352
353
354
355
356
357
358
                self.C_SourceFile.write("        return -1;\n")
                self.C_SourceFile.write("    } else {\n")
                self.C_SourceFile.write("        return BitStream_GetLength(&strm);\n")
                self.C_SourceFile.write("    }\n")
                self.C_SourceFile.write("}\n\n")
            elif encoding.lower() == "native":
                self.C_SourceFile.write(
                    "    memcpy(pBuffer, &var_%s, sizeof(asn1Scc%s) );\n" %
                    (self.CleanNameAsToolWants(nodeTypename), self.CleanNameAsToolWants(nodeTypename)))
                self.C_SourceFile.write("    return sizeof(asn1Scc%s);\n" % self.CleanNameAsToolWants(nodeTypename))
                self.C_SourceFile.write("}\n\n")

359
360
361
362
363
364
365
366
367
    def Decoder(self,
                nodeTypename: str,
                encoding: str,
                node: AsnNode,
                subProgram: ApLevelContainer,
                subProgramImplementation: str,
                param: Param,
                leafTypeDict: AST_Leaftypes,
                names: AST_Lookup) -> None:
368
369
        global fpgaSuffix
        
370
371
        tmpSpName = "Convert_From_%s_To_%s_In_%s_%s" % \
            (encoding.lower(),
372
373
374
             self.CleanNameAsADAWants(nodeTypename),
             self.CleanNameAsADAWants(subProgram._id + "_" + subProgramImplementation),
             param._id)
375
376
377
378
379
380
381
382
383
384
385

        targetVar = self.TargetVar(nodeTypename, encoding, node, subProgram, subProgramImplementation, param, leafTypeDict, names)

        if subProgramImplementation == "QGenAda":
            self.ADA_HeaderFile.write(
                "    procedure Ada_%s(T_IN : in %s; QGen_IN : out %s);\n" %
                (tmpSpName, "asn1Scc" + self.CleanNameAsToolWants(nodeTypename), self.CleanNameAsToolWants(nodeTypename)))
            self.ADA_SourceFile.write(
                "    procedure Ada_%s(T_IN : in %s; QGen_IN : out %s) is\n" %
                (tmpSpName, "asn1Scc" + self.CleanNameAsToolWants(nodeTypename), self.CleanNameAsToolWants(nodeTypename)))
            self.ADA_SourceFile.write('    begin\n')
386

387
            asn1ToTool = self.FromASN1SCCtoTool()
388
            lines = asn1ToTool.Map(
389
390
391
392
                "T_IN",
                "QGen_IN",
                node,
                leafTypeDict,
393
                names) if asn1ToTool else []
394
            lines = ["        " + x for x in lines]
395
396

            self.ADA_SourceFile.write("".join(lines))
397

398
399
400
401
402
403
404
405
            self.ADA_SourceFile.write(
                "    end Ada_%s;\n\n" % tmpSpName)
        else:
            if encoding.lower() not in self.supportedEncodings:
                panic(str(self.__class__) + ": in (%s), encoding can be one of %s (not '%s')" %  # pragma: no cover
                      (subProgram._id + "." + subProgramImplementation, self.supportedEncodings, encoding))  # pragma: no cover

            self.C_HeaderFile.write(
406
                "int %s%s(void *pBuffer, size_t iBufferSize);\n" % (tmpSpName, fpgaSuffix))
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421

            self.ADA_HeaderFile.write(
                "procedure Ada_%s(pBuffer : Interfaces.C.char_array; iBufferSize : Integer);\n" % tmpSpName)
            self.ADA_SourceFile.write(
                "procedure Ada_%s(pBuffer : Interfaces.C.char_array; iBufferSize : Integer) is\n" % tmpSpName)
            self.ADA_SourceFile.write(
                "    procedure C_%s(pBuffer : Interfaces.C.char_array; iBufferSize : Integer);\n" % tmpSpName)
            self.ADA_SourceFile.write(
                '    pragma Import(C, C_%s, "%s");\n' % (tmpSpName, tmpSpName))
            self.ADA_SourceFile.write(
                'begin\n'
                '    C_%s(pBuffer, iBufferSize);\n' % tmpSpName)
            self.ADA_SourceFile.write(
                "end Ada_%s;\n\n" % tmpSpName)
            self.C_SourceFile.write(
422
                "int %s%s(void *pBuffer, size_t iBufferSize)\n{\n" % (tmpSpName, fpgaSuffix))
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450

            if self.useOSS and encoding.lower() == "uper":
                self.C_SourceFile.write("    int pdutype = OSS_%s_PDU;\n" % self.CleanNameAsToolWants(nodeTypename))
                self.C_SourceFile.write("    STATIC OssBuf strm;\n")
                self.C_SourceFile.write("    OSS_%s *pVar_%s = NULL;\n\n" %
                                        (self.CleanNameAsToolWants(nodeTypename),
                                         self.CleanNameAsToolWants(nodeTypename)))
                self.C_SourceFile.write("    strm.value = pBuffer;\n")
                self.C_SourceFile.write("    strm.length = iBufferSize;\n")
                self.C_SourceFile.write("    if (0 == ossDecode(g_world, &pdutype, &strm, (void**)&pVar_%s)) {\n" %
                                        self.CleanNameAsToolWants(nodeTypename))
                self.C_SourceFile.write("        /* Decoding succeeded */\n")
            else:
                self.C_SourceFile.write("    STATIC asn1Scc%s var_%s;\n" %
                                        (self.CleanNameAsToolWants(nodeTypename), self.CleanNameAsToolWants(nodeTypename)))
                if encoding.lower() in ["uper", "acn"]:
                    self.C_SourceFile.write("    int errorCode;\n")
                    self.C_SourceFile.write("    STATIC BitStream strm;\n")
                    self.C_SourceFile.write("    BitStream_AttachBuffer(&strm, pBuffer, iBufferSize);\n\n")
                    self.C_SourceFile.write("    if (asn1Scc%s_%sDecode(&var_%s, &strm, &errorCode)) {\n" %
                                            (self.CleanNameAsToolWants(nodeTypename),
                                             "ACN_" if encoding.lower() == "acn" else "",
                                             self.CleanNameAsToolWants(nodeTypename)))
                    self.C_SourceFile.write("        /* Decoding succeeded */\n")
                elif encoding.lower() == "native":
                    self.C_SourceFile.write("    var_%s = *(asn1Scc%s *) pBuffer;\n    {\n" %
                                            (self.CleanNameAsToolWants(nodeTypename),
                                             self.CleanNameAsToolWants(nodeTypename)))
451

452
453
            if self.useOSS and encoding.lower() == "uper":
                asn1ToTool = self.FromOSStoTool()
454
                lines = asn1ToTool.Map(
455
456
457
458
                    "(*pVar_" + self.CleanNameAsToolWants(nodeTypename) + ")",
                    targetVar,
                    node,
                    leafTypeDict,
459
                    names) if asn1ToTool else []
460
461
            else:
                asn1ToTool = self.FromASN1SCCtoTool()
462
                lines = asn1ToTool.Map(
463
464
465
466
                    "var_" + self.CleanNameAsToolWants(nodeTypename),
                    targetVar,
                    node,
                    leafTypeDict,
467
                    names) if asn1ToTool else []
468
            lines = ["        " + x for x in lines]
469
470
471
472
473
474
            self.C_SourceFile.write("".join(lines))

            if self.useOSS and encoding.lower() == "uper":
                self.C_SourceFile.write("        ossFreeBuf(g_world, pVar_%s);\n" % self.CleanNameAsToolWants(nodeTypename))
                self.C_SourceFile.write("        return 0;\n")
                self.C_SourceFile.write("    } else {\n")
475
                self.C_SourceFile.write("#ifdef __unix__\n")
476
                self.C_SourceFile.write(
477
                    '        fprintf(stderr, "Could not decode %s (at %%s, %%d), error message was %%s\\n", __FILE__, __LINE__, ossGetErrMsg(g_world));\n' % nodeTypename)
478
                self.C_SourceFile.write("#endif\n")
479
480
481
482
483
484
                self.C_SourceFile.write("        return -1;\n")
                self.C_SourceFile.write("    }\n")
                self.C_SourceFile.write("}\n\n")
            elif encoding.lower() in ["uper", "acn"]:
                self.C_SourceFile.write("        return 0;\n")
                self.C_SourceFile.write("    } else {\n")
485
                self.C_SourceFile.write("#ifdef __unix__\n")
486
                self.C_SourceFile.write(
487
                    '        fprintf(stderr, "Could not decode %s (at %%s, %%d), error code was %%d\\n", __FILE__, __LINE__, errorCode);\n' % nodeTypename)
488
                self.C_SourceFile.write("#endif\n")
489
490
491
492
493
494
495
496
                self.C_SourceFile.write("        return -1;\n")
                self.C_SourceFile.write("    }\n")
                self.C_SourceFile.write("}\n\n")
            else:
                self.C_SourceFile.write("        return 0;\n")
                self.C_SourceFile.write("    }\n")
                self.C_SourceFile.write("}\n\n")

497
498
499
500
501
502
503
504
505
    def Common(self,
               nodeTypename: str,
               node: AsnNode,
               subProgram: ApLevelContainer,
               subProgramImplementation: str,
               param: Param,
               leafTypeDict: AST_Leaftypes,
               names: AST_Lookup) -> None:
        if isinstance(param, (InOutParam, InParam)):
506
            self.Decoder(nodeTypename, param._sourceElement._encoding, node, subProgram, subProgramImplementation, param, leafTypeDict, names)
507
        if isinstance(param, (InOutParam, OutParam)):
508
509
            self.Encoder(nodeTypename, param._sourceElement._encoding, node, subProgram, subProgramImplementation, param, leafTypeDict, names)

510
    def OnBasic(self, nodeTypename: str, node: AsnNode, subProgram: ApLevelContainer, subProgramImplementation: str, param: Param, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> None:
511
512
513
514
        realLeafType = leafTypeDict[nodeTypename]
        inform(str(self.__class__) + ": BASE: %s (%s)", nodeTypename, realLeafType)
        self.Common(nodeTypename, node, subProgram, subProgramImplementation, param, leafTypeDict, names)

515
    def OnSequence(self, nodeTypename: str, node: AsnNode, subProgram: ApLevelContainer, subProgramImplementation: str, param: Param, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> None:
516
517
518
        inform(str(self.__class__) + ": SEQUENCE: %s", nodeTypename)
        self.Common(nodeTypename, node, subProgram, subProgramImplementation, param, leafTypeDict, names)

519
    def OnSet(self, nodeTypename: str, node: AsnNode, subProgram: ApLevelContainer, subProgramImplementation: str, param: Param, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> None:
520
521
522
        inform(str(self.__class__) + ": SET: %s", nodeTypename)  # pragma: nocover
        self.Common(nodeTypename, node, subProgram, subProgramImplementation, param, leafTypeDict, names)  # pragma: nocover

523
    def OnEnumerated(self, nodeTypename: str, node: AsnNode, subProgram: ApLevelContainer, subProgramImplementation: str, param: Param, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> None:
524
525
526
        inform(str(self.__class__) + ": ENUMERATED: %s", nodeTypename)
        self.Common(nodeTypename, node, subProgram, subProgramImplementation, param, leafTypeDict, names)

527
    def OnSequenceOf(self, nodeTypename: str, node: AsnNode, subProgram: ApLevelContainer, subProgramImplementation: str, param: Param, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> None:
528
529
530
        inform(str(self.__class__) + ": SEQUENCEOF: %s", nodeTypename)
        self.Common(nodeTypename, node, subProgram, subProgramImplementation, param, leafTypeDict, names)

531
    def OnSetOf(self, nodeTypename: str, node: AsnNode, subProgram: ApLevelContainer, subProgramImplementation: str, param: Param, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> None:
532
533
534
        inform(str(self.__class__) + ": SETOF: %s", nodeTypename)  # pragma: nocover
        self.Common(nodeTypename, node, subProgram, subProgramImplementation, param, leafTypeDict, names)  # pragma: nocover

535
    def OnChoice(self, nodeTypename: str, node: AsnNode, subProgram: ApLevelContainer, subProgramImplementation: str, param: Param, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> None:
536
537
538
        inform(str(self.__class__) + ": CHOICE: %s", nodeTypename)
        self.Common(nodeTypename, node, subProgram, subProgramImplementation, param, leafTypeDict, names)

539
    def OnShutdown(self, modelingLanguage: str, asnFile: str, sp: ApLevelContainer, subProgramImplementation: str, maybeFVname: str) -> None:
540
541
542
543
        global genHwDevDrv
        global fpgaSuffix
        global dispatcherSuffix
        
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
        if modelingLanguage == "QGenAda":
            self.ADA_HeaderFile.write("    procedure Execute_%s (" % self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation))
            self.ADA_SourceFile.write("    procedure Execute_%s (" % self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation))
            for param in sp._params:
                if param._id != sp._params[0]._id:
                    self.ADA_HeaderFile.write('; ')
                    self.ADA_SourceFile.write('; ')
                self.ADA_HeaderFile.write(self.CleanNameAsToolWants(param._id) + " : access asn1Scc" + self.CleanNameAsToolWants(param._signal._asnNodename))
                self.ADA_SourceFile.write(self.CleanNameAsToolWants(param._id) + " : access asn1Scc" + self.CleanNameAsToolWants(param._signal._asnNodename))

            self.ADA_HeaderFile.write(");\n")
            self.ADA_SourceFile.write(") is\n")
            for param in sp._params:
                self.ADA_SourceFile.write("        %s : aliased %s;\n" % ("QGen_" + self.CleanNameAsToolWants(param._id), self.CleanNameAsToolWants(param._signal._asnNodename)))
            self.ADA_SourceFile.write("    begin\n\n")
            for param in sp._params:
                nodeTypename = param._signal._asnNodename
                encoding = param._sourceElement._encoding
                tmpSpName = "Ada_Convert_From_%s_To_%s_In_%s_%s" % \
                    (encoding.lower(),
                     self.CleanNameAsADAWants(nodeTypename),
                     self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation),
                     self.CleanNameAsADAWants(param._id))
                if isinstance(param, InParam):
568
569
570
571
572
                    self.ADA_SourceFile.write(
                        '        %s(%s.all, QGen_%s);\n' % (
                            tmpSpName,
                            self.CleanNameAsToolWants(param._id),
                            self.CleanNameAsToolWants(param._id)))
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590

            self.ADA_SourceFile.write("\n        %s.comp (" % self.CleanNameAsADAWants(sp._id))
            for param in sp._params:
                if param._id != sp._params[0]._id:
                    self.ADA_SourceFile.write(', ')
                self.ADA_SourceFile.write("QGen_" + self.CleanNameAsToolWants(param._id))
            self.ADA_SourceFile.write(");\n\n")

            # Encode outputs
            for param in sp._params:
                nodeTypename = param._signal._asnNodename
                encoding = param._sourceElement._encoding
                tmpSpName = "Ada_Convert_From_%s_To_%s_In_%s_%s" % \
                    (self.CleanNameAsADAWants(nodeTypename),
                     encoding.lower(),
                     self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation),
                     param._id)
                if isinstance(param, InOutParam) or isinstance(param, OutParam):
591
592
593
594
595
                    self.ADA_SourceFile.write(
                        '        %s(QGen_%s, %s.all);\n' % (
                            tmpSpName,
                            self.CleanNameAsToolWants(param._id),
                            self.CleanNameAsToolWants(param._id)))
596
597
598
599
600
601
602
603
604
            self.ADA_SourceFile.write("    end Execute_%s;\n" % self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation))
            self.ADA_SourceFile.write(
                'end %s;\n' %
                self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation + "_wrapper"))
            self.ADA_HeaderFile.write(
                'end %s;\n' %
                self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation + "_wrapper"))

        else:
605
            if genHwDevDrv:
Tiago Jorge's avatar
Tiago Jorge committed
606
607
608
609
                if maybeFVname not in brave_seen:
                    brave_seen[maybeFVname] = 'no_init_yet';
                else:
                    brave_seen[maybeFVname] = 'with_init_already'
610
            
611
612
            if genHwDevDrv:
                self.C_HeaderFile.write("int Execute_%s%s();\n" % (self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation), fpgaSuffix))
613
614
            else:    
                self.C_HeaderFile.write("void Execute_%s();\n" % self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation))
615
            if maybeFVname != "":
616
                if not (genHwDevDrv and maybeFVname in brave_seen and brave_seen[maybeFVname] is 'with_init_already'):
Tiago Jorge's avatar
Tiago Jorge committed
617
                    self.C_HeaderFile.write("void init_%s%s();\n" % (self.CleanNameAsADAWants(maybeFVname), fpgaSuffix))
618
                if genHwDevDrv:
619
                    self.C_HeaderFile.write("int %s_%s%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id), fpgaSuffix))
620
621
                else:
                    self.C_HeaderFile.write("void %s_%s%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id), fpgaSuffix))
622
            else:  # pragma: no cover
623
624
                self.C_HeaderFile.write("void %s_init%s();\n" % (self.CleanNameAsADAWants(sp._id), fpgaSuffix))  # pragma: no cover
                self.C_HeaderFile.write("void %s%s(" % (self.CleanNameAsADAWants(sp._id), fpgaSuffix))  # pragma: no cover
625
626
627
628
629
630
631
632
            for param in sp._params:
                if param._id != sp._params[0]._id:
                    self.C_HeaderFile.write(', ')
                if isinstance(param, InParam):
                    self.C_HeaderFile.write('void *p' + self.CleanNameAsToolWants(param._id) + ', size_t size_' + self.CleanNameAsToolWants(param._id))
                else:
                    self.C_HeaderFile.write('void *p' + self.CleanNameAsToolWants(param._id) + ', size_t *pSize_' + self.CleanNameAsToolWants(param._id))
            self.C_HeaderFile.write(");\n")
633
634
            
            # Check if Function Block will exist both as SW and HW. If yes generate dispatcher function (to delegate to SW or HW).
635
636
637
            # Dispatcher <Function Block name>_<PI name><dispatcherSuffix> is part of the FPGA device driver <PI name>_<Language>.vhdl.h/c
            # Dispatcher can return: 0 (successfully delegated to HW), 1 (delegated to SW), 2 (unsuccessfully delegated to HW)
            # Here being added to the .h file
638
            if genHwDevDrv:
639
                if maybeFVname != "":
640
                    self.C_HeaderFile.write("int %s_%s%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id), dispatcherSuffix))
641
                else:  # pragma: no cover
642
                    self.C_HeaderFile.write("int %s%s(" % (self.CleanNameAsADAWants(sp._id), dispatcherSuffix))  # pragma: no cover                    
643
644
645
646
647
648
649
650
651
                for param in sp._params:
                    if param._id != sp._params[0]._id:
                        self.C_HeaderFile.write(', ')
                    if isinstance(param, InParam):
                        self.C_HeaderFile.write('void *p' + self.CleanNameAsToolWants(param._id) + ', size_t size_' + self.CleanNameAsToolWants(param._id))
                    else:
                        self.C_HeaderFile.write('void *p' + self.CleanNameAsToolWants(param._id) + ', size_t *pSize_' + self.CleanNameAsToolWants(param._id))
                self.C_HeaderFile.write(");\n")            
            
652
653
            self.C_HeaderFile.write("\n#endif\n")

654
655
            if genHwDevDrv:
                self.C_SourceFile.write("int Execute_%s%s()\n{\n" % (self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation), fpgaSuffix))
656
657
            else:
                self.C_SourceFile.write("void Execute_%s()\n{\n" % self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation))
658
659
660
661
            self.ExecuteBlock(modelingLanguage, asnFile, sp, subProgramImplementation, maybeFVname)
            self.C_SourceFile.write("}\n\n")

            if maybeFVname != "":
662
                if not (genHwDevDrv and maybeFVname in brave_seen and brave_seen[maybeFVname] is 'with_init_already'):
Tiago Jorge's avatar
Tiago Jorge committed
663
                    self.C_SourceFile.write("void init_%s%s()\n" % (self.CleanNameAsADAWants(maybeFVname), fpgaSuffix))
664
665
            else:  # pragma: no cover
                self.C_SourceFile.write("void %s_init()\n" % self.CleanNameAsADAWants(sp._id))  # pragma: no cover
666
            if not (genHwDevDrv and maybeFVname in brave_seen and brave_seen[maybeFVname] is 'with_init_already'):
Tiago Jorge's avatar
Tiago Jorge committed
667
668
669
670
671
672
                self.C_SourceFile.write("{\n")
                self.InitializeBlock(modelingLanguage, asnFile, sp, subProgramImplementation, maybeFVname)
                # self.C_SourceFile.write("    extern void InitializeGlue();\n")
                # self.C_SourceFile.write("    InitializeGlue();\n")
                self.C_SourceFile.write("}\n\n")

673
            if maybeFVname != "":
674
                if genHwDevDrv:
675
                    self.C_SourceFile.write("int %s_%s%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id), fpgaSuffix))
676
677
                else:
                    self.C_SourceFile.write("void %s_%s%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id), fpgaSuffix))
678
679
680
681
682
683
684
685
686
687
688
            else:  # pragma: no cover
                self.C_SourceFile.write("void %s(" % self.CleanNameAsADAWants(sp._id))  # pragma: no cover
            for param in sp._params:
                if param._id != sp._params[0]._id:
                    self.C_SourceFile.write(', ')
                if isinstance(param, InParam):
                    self.C_SourceFile.write('void *p' + self.CleanNameAsToolWants(param._id) + ', size_t size_' + self.CleanNameAsToolWants(param._id))
                else:
                    self.C_SourceFile.write('void *p' + self.CleanNameAsToolWants(param._id) + ', size_t *pSize_' + self.CleanNameAsToolWants(param._id))
            self.C_SourceFile.write(")\n{\n")

689
690
691
692
693
694
695
696
697
            # Call Dispatcher function
            # Dispatcher will delegate to one or the other side (SW or HW) depending on whether the value of the global variable storing the current
            # configuration equals one of those configurations defined for the target Function Block (in IV field listing the FPGA configurations)
            # Mechanism is as follows:
            # 1) SW side glue <PI name>_<Language>.<Language>.h/c calls HW side glue (device driver) <PI name>_<Language>.vhdl.h/c
            #   specifically <Function Block name>_<PI name> function calls the Dispatcher <Function Block name>_<PI name><dispatcherSuffix>
            # 2) Dispatcher in HW side delegates back to SW side (when returning 1 or 2) or to FPGA (and returns 0)
            # 3) If successfully delegated to HW (returning 0), SW side returns immediately so to avoid calling up SW side as well
            #   Otherwise execution continues up trough "normal" SW side calling
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
            if sp._fpgaConfigurations is not '' and subProgramImplementation.lower() == "simulink" and modelingLanguage != "vhdl":
                self.C_SourceFile.write('    // Calling Brave VHDL dispatcher function\n')
                self.C_SourceFile.write('    if (0 == %s_%s%s (' % \
                                                    (self.CleanNameAsADAWants(maybeFVname),
                                                     self.CleanNameAsADAWants(sp._id),
                                                     dispatcherSuffix))
                for param in sp._params:
                    if param._id != sp._params[0]._id:
                        self.C_SourceFile.write(', ')
                    if isinstance(param, InParam):
                        self.C_SourceFile.write('p' + self.CleanNameAsToolWants(param._id) + ', size_' + self.CleanNameAsToolWants(param._id))
                    else:
                        self.C_SourceFile.write('p' + self.CleanNameAsToolWants(param._id) + ', pSize_' + self.CleanNameAsToolWants(param._id))                                                
                self.C_SourceFile.write(")) return;\n")
                
713
            if genHwDevDrv:
714
715
716
717
718
719
                self.C_SourceFile.write('    // Check if FPGA is ready.\n')
                self.C_SourceFile.write('    extern const char globalFpgaStatus_%s[];\n' % (self.CleanNameAsADAWants(maybeFVname)))
                self.C_SourceFile.write('    if(strcmp(globalFpgaStatus_%s, FPGA_READY)){\n' % (self.CleanNameAsADAWants(maybeFVname)))
                self.C_SourceFile.write('       return -1;\n')
                self.C_SourceFile.write('    }\n\n')

720
721
722
723
            # Decode inputs
            for param in sp._params:
                nodeTypename = param._signal._asnNodename
                encoding = param._sourceElement._encoding
724
                tmpSpName = "Convert_From_%s_To_%s_In_%s_%s%s" % \
725
726
727
                    (encoding.lower(),
                     self.CleanNameAsADAWants(nodeTypename),
                     self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation),
728
729
                     self.CleanNameAsADAWants(param._id),
                     fpgaSuffix)
730
731
732
733
734
735
736
737
738
739
740
741
                if isinstance(param, InParam):
                    self.C_SourceFile.write('    %s(p%s, size_%s);\n' %
                                            (tmpSpName,
                                             self.CleanNameAsToolWants(param._id),
                                             self.CleanNameAsToolWants(param._id)))
                elif isinstance(param, InOutParam):
                    self.C_SourceFile.write('    %s(p%s, *pSize_%s);\n' %  # pragma: no cover
                                            (tmpSpName,
                                             self.CleanNameAsToolWants(param._id),
                                             self.CleanNameAsToolWants(param._id)))  # pragma: no cover

            # Do functional work
742
743
            if genHwDevDrv:
                self.C_SourceFile.write("    if(Execute_%s%s()) return -1;\n" % (self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation), fpgaSuffix))
744
745
            else:
                self.C_SourceFile.write("    Execute_%s();\n" % self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation))
746
747
748
749
750

            # Encode outputs
            for param in sp._params:
                nodeTypename = param._signal._asnNodename
                encoding = param._sourceElement._encoding
751
                tmpSpName = "Convert_From_%s_To_%s_In_%s_%s%s" % \
752
753
754
                    (self.CleanNameAsADAWants(nodeTypename),
                     encoding.lower(),
                     self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation),
755
756
                     param._id,
                     fpgaSuffix)
757
758
759
760
761
762
                if isinstance(param, InOutParam) or isinstance(param, OutParam):
                    self.C_SourceFile.write('    *pSize_%s = %s(p%s, %s);\n' %
                                            (self.CleanNameAsToolWants(param._id),
                                             tmpSpName,
                                             self.CleanNameAsToolWants(param._id),
                                             param._signal._asnSize))
763
            if genHwDevDrv:
764
                self.C_SourceFile.write("    return 0;\n")
765
766
            self.C_SourceFile.write("}\n\n")

767
            # Check if Function Block will exist both as SW and HW. If yes generate dispatcher function (to delegate to SW or HW).
768
769
770
            # Dispatcher <Function Block name>_<PI name><dispatcherSuffix> is part of the FPGA device driver <PI name>_<Language>.vhdl.h/c
            # Dispatcher can return: 0 (successfully delegated to HW), 1 (delegated to SW), 2 (unsuccessfully delegated to HW)
            # Here being added to the .c file
771
            if genHwDevDrv:
772
                if maybeFVname != "":
773
                    self.C_SourceFile.write("int %s_%s%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id), dispatcherSuffix))
774
                else:  # pragma: no cover
775
                    self.C_SourceFile.write("int %s%s(" % (self.CleanNameAsADAWants(sp._id), dispatcherSuffix))  # pragma: no cover                    
776
777
778
779
780
781
782
783
                for param in sp._params:
                    if param._id != sp._params[0]._id:
                        self.C_SourceFile.write(', ')
                    if isinstance(param, InParam):
                        self.C_SourceFile.write('void *p' + self.CleanNameAsToolWants(param._id) + ', size_t size_' + self.CleanNameAsToolWants(param._id))
                    else:
                        self.C_SourceFile.write('void *p' + self.CleanNameAsToolWants(param._id) + ', size_t *pSize_' + self.CleanNameAsToolWants(param._id))
                self.C_SourceFile.write(")\n{\n")
784
785
786
787
                self.C_SourceFile.write('    /*\n')
                self.C_SourceFile.write('    Delegate to one or the other side (SW or HW) depending on whether the value of a global variable storing the current\n')
                self.C_SourceFile.write('    configuration equals one of those defined for the target function in new IV field.\n')
                self.C_SourceFile.write('    */\n')
788
789
790
                self.C_SourceFile.write('    extern const char p_szGlobalState[];\n')
                self.C_SourceFile.write('    char *fConfig;\n')
                self.C_SourceFile.write('    char fConfigList[30] = "%s";\n' % (sp._fpgaConfigurations))
791
                self.C_SourceFile.write('    char allModes[] = "AllModes";\n')
792
                self.C_SourceFile.write('    fConfig = strtok(fConfigList, ",");\n')
793
                self.C_SourceFile.write('    while( fConfig != NULL ) {\n')
794
                self.C_SourceFile.write('       if(!strcmp(p_szGlobalState, fConfig) || !strcmp(allModes, fConfig)){\n')
795
                self.C_SourceFile.write('           // delegate to HW\n')
796
                self.C_SourceFile.write('           LOGDEBUG("[ <-?-> <-?-> <-?-> %s Dispatcher <-?-> <-?-> <-?-> ] Delegating to HW ... \\n");\n' % (self.CleanNameAsADAWants(maybeFVname)))
797
                self.C_SourceFile.write("           if(%s_%s%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id), fpgaSuffix))
798
799
800
801
802
803
804
                for param in sp._params:
                    if param._id != sp._params[0]._id:
                        self.C_SourceFile.write(', ')
                    if isinstance(param, InParam):
                        self.C_SourceFile.write('p' + self.CleanNameAsToolWants(param._id) + ', size_' + self.CleanNameAsToolWants(param._id))
                    else:
                        self.C_SourceFile.write('p' + self.CleanNameAsToolWants(param._id) + ', pSize_' + self.CleanNameAsToolWants(param._id))
805
806
                self.C_SourceFile.write(")){\n")
                self.C_SourceFile.write('               // HW error, return 2\n')
807
                self.C_SourceFile.write('               LOGERROR("[ <-?-> <-?-> <-?-> %s Dispatcher <-?-> <-?-> <-?-> ] HW error!\\n");\n' % (self.CleanNameAsADAWants(maybeFVname)))
808
809
                self.C_SourceFile.write('               return 2;\n')
                self.C_SourceFile.write('           }\n')
810
811
812
                self.C_SourceFile.write('           // delegated to HW, return 0\n')
                self.C_SourceFile.write('           return 0;\n')
                self.C_SourceFile.write('       }\n')
813
                self.C_SourceFile.write('       fConfig = strtok(NULL, ",");\n')
814
                self.C_SourceFile.write('    }\n')
815
                self.C_SourceFile.write('    LOGDEBUG("[ <-?-> <-?-> <-?-> %s Dispatcher <-?-> <-?-> <-?-> ] Delegating to SW ...\\n");\n' % (self.CleanNameAsADAWants(maybeFVname)))
816
817
                self.C_SourceFile.write('    // delegate to SW, return 1\n')
                self.C_SourceFile.write('    return 1;\n')
818
819
                self.C_SourceFile.write("}\n\n")

820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
            self.ADA_HeaderFile.write(
                "procedure Ada_Execute_%s;\n" % self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation))
            self.ADA_HeaderFile.write('\nend %s;\n' % self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation))
            self.ADA_SourceFile.write(
                "procedure Ada_Execute_%s is\n" %
                self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation))
            self.ADA_SourceFile.write(
                "    procedure C_Execute_%s;\n" %
                self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation))
            self.ADA_SourceFile.write(
                '    pragma Import(C, C_Execute_%s, "Execute_%s");\n' %
                (
                    self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation),
                    self.CleanNameAsToolWants(sp._id + "_" + subProgramImplementation),
                ))

            self.ADA_SourceFile.write(
                'begin\n    C_Execute_%s;\n' %
                self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation))
            self.ADA_SourceFile.write(
                "end Ada_Execute_%s;\n\n" %
                self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation))
            self.ADA_SourceFile.write('\nend %s;\n' % self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation))
843
844
845


SynchronousToolGlueGenerator = SynchronousToolGlueGeneratorGeneric[str, str]