simulink_B_mapper.py 28.5 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#
# (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.
#
'''
This is the code generator for the Simulink code mappers.
This backend is called by aadl2glueC, when a Simulink subprogram
is identified in the input concurrency view.

This code generator supports both UPER/ACN and Native encodings,
and also supports UPER/ACN using both ASN1SCC and Nokalva.

Matlab/Simulink is a member of the synchronous "club" (SCADE, etc) ;
The subsystem developer (or rather, the APLC developer) is
building a model in Simulink, and the generated code is offered
in the form of a "function" that does all the work.
To that end, we create "glue" functions for input and output
parameters, which have C callable interfaces. The necessary
stubs (to allow calling from the VM side) are also generated.
'''

38
39
from typing import List

40
from ..commonPy.utility import panicWithCallStack
41
42
from ..commonPy.asnAST import (
    AsnInt, AsnReal, AsnBool, AsnEnumerated, isSequenceVariable, sourceSequenceLimit,
43
44
    AsnOctetString, AsnSequenceOrSet, AsnSequenceOrSetOf, AsnChoice, AsnNode,
    AsnSequenceOf, AsnSetOf, AsnSequence, AsnSet, AsnMetaMember)
45
from ..commonPy.aadlAST import AadlPort, AadlParameter, ApLevelContainer, Param
46
from ..commonPy.asnParser import AST_Lookup, AST_Leaftypes
47

48
from ..commonPy.recursiveMapper import RecursiveMapper
49
50
from .synchronousTool import SynchronousToolGlueGenerator

51
52
import os

53
54
55
56
isAsynchronous = False
simulinkBackend = None


57
def IsElementMappedToPrimitive(node: AsnSequenceOrSetOf, names: AST_Lookup) -> bool:
58
59
60
    contained = node._containedType
    while isinstance(contained, str):
        contained = names[contained]
61
    return isinstance(contained, (AsnInt, AsnReal, AsnBool, AsnEnumerated))
62
63


Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
64
# pylint: disable=no-self-use
65
class FromSimulinkToASN1SCC(RecursiveMapper):
66
    def MapInteger(self, srcSimulink: str, destVar: str, _: AsnInt, __: AST_Leaftypes, ___: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
67
68
        return ["%s = (asn1SccSint) %s;\n" % (destVar, srcSimulink)]

69
    def MapReal(self, srcSimulink: str, destVar: str, _: AsnReal, __: AST_Leaftypes, ___: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
70
71
        return ["%s = (double) %s;\n" % (destVar, srcSimulink)]

72
    def MapBoolean(self, srcSimulink: str, destVar: str, _: AsnBool, __: AST_Leaftypes, ___: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
73
74
        return ["%s = (asn1SccUint) %s;\n" % (destVar, srcSimulink)]

75
    def MapOctetString(self, srcSimulink: str, destVar: str, node: AsnOctetString, _: AST_Leaftypes, __: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
76
        lines = []  # type: List[str]
77
        if not node._range:
78
79
80
81
82
83
            panicWithCallStack("OCTET STRING (in %s) must have a SIZE constraint inside ASN.1,\nor else we can't generate C code!" % node.Location())  # pragma: no cover
        for i in range(0, node._range[-1]):
            lines.append("%s.arr[%d] = %s.element_data[%d];\n" % (destVar, i, srcSimulink, i))
        if isSequenceVariable(node):
            lines.append("%s.nCount = %s.length;\n" % (destVar, srcSimulink))
        # No nCount anymore
84
85
        # else:
        #     lines.append("%s.nCount = %s;\n" % (destVar, node._range[-1]))
86
87
        return lines

88
    def MapEnumerated(self, srcSimulink: str, destVar: str, _: AsnEnumerated, __: AST_Leaftypes, ___: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
89
90
        return ["%s = %s;\n" % (destVar, srcSimulink)]

91
    def MapSequence(self, srcSimulink: str, destVar: str, node: AsnSequenceOrSet, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
92
        lines = []  # type: List[str]
93
94
95
96
97
98
99
100
101
102
        for child in node._members:
            lines.extend(
                self.Map(
                    "%s.%s" % (srcSimulink, self.CleanName(child[0])),
                    destVar + "." + self.CleanName(child[0]),
                    child[1],
                    leafTypeDict,
                    names))
        return lines

103
    def MapSet(self, srcSimulink: str, destVar: str, node: AsnSequenceOrSet, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
104
105
        return self.MapSequence(srcSimulink, destVar, node, leafTypeDict, names)  # pragma: nocover

106
    def MapChoice(self, srcSimulink: str, destVar: str, node: AsnChoice, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
107
        lines = []  # type: List[str]
108
109
110
111
        childNo = 0
        for child in node._members:
            childNo += 1
            lines.append("%sif (%s.choiceIdx == %d) {\n" % (self.maybeElse(childNo), srcSimulink, childNo))
112
            lines.extend(
113
                ['    ' + x
114
115
116
117
118
119
                 for x in self.Map(
                     "%s.%s" % (srcSimulink, self.CleanName(child[0])),
                     destVar + ".u." + self.CleanName(child[0]),
                     child[1],
                     leafTypeDict,
                     names)])
120
121
122
123
            lines.append("    %s.kind = %s;\n" % (destVar, self.CleanName(child[2])))
            lines.append("}\n")
        return lines

124
    def MapSequenceOf(self, srcSimulink: str, destVar: str, node: AsnSequenceOrSetOf, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
125
        if not node._range:
126
127
            panicWithCallStack("need a SIZE constraint or else we can't generate C code (%s)!\n" % node.Location())  # pragma: no cover
        isMappedToPrimitive = IsElementMappedToPrimitive(node, names)
Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
128
        lines = []  # type: List[str]
129
        for i in range(0, node._range[-1]):
130
            lines.extend(
131
                self.Map(("%s.element_data[%d]" % (srcSimulink, i)) if isMappedToPrimitive else ("%s.element_%02d" % (srcSimulink, i)),
132
133
134
135
136
137
138
                         destVar + ".arr[%d]" % i,
                         node._containedType,
                         leafTypeDict,
                         names))
        if isSequenceVariable(node):
            lines.append("%s.nCount = %s.length;\n" % (destVar, srcSimulink))
        # No nCount anymore
139
140
        # else:
        #     lines.append("%s.nCount = %s;\n" % (destVar, node._range[-1]))
141
142
        return lines

143
    def MapSetOf(self, srcSimulink: str, destVar: str, node: AsnSequenceOrSetOf, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
144
145
146
        return self.MapSequenceOf(srcSimulink, destVar, node, leafTypeDict, names)  # pragma: nocover


Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
147
# pylint: disable=no-self-use
148
class FromASN1SCCtoSimulink(RecursiveMapper):
149
    def MapInteger(self, srcVar: str, dstSimulink: str, _: AsnInt, __: AST_Leaftypes, ___: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
150
151
        return ["%s = %s;\n" % (dstSimulink, srcVar)]

152
    def MapReal(self, srcVar: str, dstSimulink: str, _: AsnReal, __: AST_Leaftypes, ___: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
153
154
        return ["%s = %s;\n" % (dstSimulink, srcVar)]

155
    def MapBoolean(self, srcVar: str, dstSimulink: str, _: AsnBool, __: AST_Leaftypes, ___: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
156
157
        return ["%s = %s;\n" % (dstSimulink, srcVar)]

158
    def MapOctetString(self, srcVar: str, dstSimulink: str, node: AsnOctetString, _: AST_Leaftypes, __: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
159
        if not node._range:
160
161
            panicWithCallStack("OCTET STRING (in %s) must have a SIZE constraint inside ASN.1,\nor else we can't generate C code!" % node.Location())  # pragma: no cover

Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
162
        lines = []  # type: List[str]
163
        limit = sourceSequenceLimit(node, srcVar)
164
165
        lines.append("unsigned int i=0;\n")
        lines.append("for(i=0; i<%s; i++)\n        %s.element_data[i] = %s.arr[i];\n" % (limit, dstSimulink, srcVar))
166

167
        if len(node._range) > 1 and node._range[0] != node._range[1]:
168
169
170
            lines.append("%s.length = %s;\n" % (dstSimulink, limit))
        return lines

171
    def MapEnumerated(self, srcVar: str, dstSimulink: str, node: AsnEnumerated, __: AST_Leaftypes, ___: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
172
173
174
175
        if None in [x[1] for x in node._members]:
            panicWithCallStack("an ENUMERATED must have integer values! (%s)" % node.Location())  # pragma: no cover
        return ["%s = %s;\n" % (dstSimulink, srcVar)]

176
    def MapSequence(self, srcVar: str, dstSimulink: str, node: AsnSequenceOrSet, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
177
        lines = []  # type: List[str]
178
179
180
181
182
183
184
185
186
187
        for child in node._members:
            lines.extend(
                self.Map(
                    srcVar + "." + self.CleanName(child[0]),
                    "%s.%s" % (dstSimulink, self.CleanName(child[0])),
                    child[1],
                    leafTypeDict,
                    names))
        return lines

188
    def MapSet(self, srcVar: str, dstSimulink: str, node: AsnSequenceOrSet, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
189
190
        return self.MapSequence(srcVar, dstSimulink, node, leafTypeDict, names)  # pragma: nocover

191
    def MapChoice(self, srcVar: str, dstSimulink: str, node: AsnChoice, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
192
        lines = []  # type: List[str]
193
194
195
196
        childNo = 0
        for child in node._members:
            childNo += 1
            lines.append("%sif (%s.kind == %s) {\n" % (self.maybeElse(childNo), srcVar, self.CleanName(child[2])))
197
            lines.extend(
198
                ['    ' + x
199
200
201
202
203
204
                 for x in self.Map(
                     srcVar + ".u." + self.CleanName(child[0]),
                     "%s.%s" % (dstSimulink, self.CleanName(child[0])),
                     child[1],
                     leafTypeDict,
                     names)])
205
206
207
208
            lines.append("    %s.choiceIdx = %d;\n" % (dstSimulink, childNo))
            lines.append("}\n")
        return lines

209
    def MapSequenceOf(self, srcVar: str, dstSimulink: str, node: AsnSequenceOrSetOf, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
210
        if not node._range:
211
212
            panicWithCallStack("need a SIZE constraint or else we can't generate C code (%s)!\n" % node.Location())  # pragma: no cover
        isMappedToPrimitive = IsElementMappedToPrimitive(node, names)
Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
213
        lines = []  # type: List[str]
214
215
216
        for i in range(0, node._range[-1]):
            lines.extend(self.Map(
                srcVar + ".arr[%d]" % i,
217
                ("%s.element_data[%d]" % (dstSimulink, i)) if isMappedToPrimitive else ("%s.element_%02d" % (dstSimulink, i)),
218
219
220
221
222
223
224
                node._containedType,
                leafTypeDict,
                names))
        if isSequenceVariable(node):
            lines.append("%s.length = %s.nCount;\n" % (dstSimulink, srcVar))
        return lines

225
    def MapSetOf(self, srcVar: str, dstSimulink: str, node: AsnSequenceOrSetOf, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
226
227
228
        return self.MapSequenceOf(srcVar, dstSimulink, node, leafTypeDict, names)  # pragma: nocover


Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
229
# pylint: disable=no-self-use
230
class FromSimulinkToOSS(RecursiveMapper):
231
    def MapInteger(self, srcSimulink: str, destVar: str, _: AsnInt, __: AST_Leaftypes, ___: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
232
233
        return ["%s = %s;\n" % (destVar, srcSimulink)]

234
    def MapReal(self, srcSimulink: str, destVar: str, _: AsnReal, __: AST_Leaftypes, ___: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
235
236
        return ["%s = %s;\n" % (destVar, srcSimulink)]

237
    def MapBoolean(self, srcSimulink: str, destVar: str, _: AsnBool, __: AST_Leaftypes, ___: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
238
239
        return ["%s = (char) %s;\n" % (destVar, srcSimulink)]

240
    def MapOctetString(self, srcSimulink: str, destVar: str, node: AsnOctetString, _: AST_Leaftypes, __: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
241
        lines = []  # type: List[str]
242
        if not node._range:
243
244
245
            panicWithCallStack("OCTET STRING (in %s) must have a SIZE constraint inside ASN.1,\nor else we can't generate C code!" % node.Location())  # pragma: no cover
        for i in range(0, node._range[-1]):
            lines.append("%s.value[%d] = %s.element_data[%d];\n" % (destVar, i, srcSimulink, i))
246
        if len(node._range) > 1 and node._range[0] != node._range[1]:
247
248
249
250
251
            lines.append("%s.length = %s.length;\n" % (destVar, srcSimulink))
        else:
            lines.append("%s.length = %s;\n" % (destVar, node._range[-1]))
        return lines

252
    def MapEnumerated(self, srcSimulink: str, destVar: str, _: AsnEnumerated, __: AST_Leaftypes, ___: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
253
254
        return ["%s = %s;\n" % (destVar, srcSimulink)]

255
    def MapSequence(self, srcSimulink: str, destVar: str, node: AsnSequenceOrSet, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
256
        lines = []  # type: List[str]
257
258
259
260
261
262
263
264
265
266
        for child in node._members:
            lines.extend(
                self.Map(
                    "%s.%s" % (srcSimulink, self.CleanName(child[0])),
                    destVar + "." + self.CleanName(child[0]),
                    child[1],
                    leafTypeDict,
                    names))
        return lines

267
    def MapSet(self, srcSimulink: str, destVar: str, node: AsnSequenceOrSet, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
268
269
        return self.MapSequence(srcSimulink, destVar, node, leafTypeDict, names)  # pragma: nocover

270
    def MapChoice(self, srcSimulink: str, destVar: str, node: AsnChoice, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
271
        lines = []  # type: List[str]
272
273
274
275
        childNo = 0
        for child in node._members:
            childNo += 1
            lines.append("%sif (%s.choiceIdx == %d) {\n" % (self.maybeElse(childNo), srcSimulink, childNo))
276
            lines.extend(
277
                ['    ' + x
278
279
280
281
282
283
                 for x in self.Map(
                     "%s.%s" % (srcSimulink, self.CleanName(child[0])),
                     destVar + ".u." + self.CleanName(child[0]),
                     child[1],
                     leafTypeDict,
                     names)])
284
285
286
287
            lines.append("    %s.choice = OSS_%s_chosen;\n" % (destVar, self.CleanName(child[0])))
            lines.append("}\n")
        return lines

288
    def MapSequenceOf(self, srcSimulink: str, destVar: str, node: AsnSequenceOrSetOf, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
289
        if not node._range:
290
291
            panicWithCallStack("(%s) needs a SIZE constraint or else we can't generate C code!\n" % node.Location())  # pragma: no cover
        isMappedToPrimitive = IsElementMappedToPrimitive(node, names)
Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
292
        lines = []  # type: List[str]
293
        for i in range(0, node._range[-1]):
294
            lines.extend(
295
                self.Map(("%s.element_data[%d]" % (srcSimulink, i)) if isMappedToPrimitive else ("%s.element_%02d" % (srcSimulink, i)),
296
297
298
299
                         destVar + ".value[%d]" % i,
                         node._containedType,
                         leafTypeDict,
                         names))
300
        if len(node._range) > 1 and node._range[0] != node._range[1]:
301
302
303
304
305
            lines.append("%s.count = %s.length;\n" % (destVar, srcSimulink))
        else:
            lines.append("%s.count = %s;\n" % (destVar, node._range[-1]))
        return lines

306
    def MapSetOf(self, srcSimulink: str, destVar: str, node: AsnSequenceOrSetOf, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
307
308
309
        return self.MapSequenceOf(srcSimulink, destVar, node, leafTypeDict, names)  # pragma: nocover


Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
310
# pylint: disable=no-self-use
311
class FromOSStoSimulink(RecursiveMapper):
312
    def MapInteger(self, srcVar: str, dstSimulink: str, _: AsnInt, __: AST_Leaftypes, ___: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
313
314
        return ["%s = %s;\n" % (dstSimulink, srcVar)]

315
    def MapReal(self, srcVar: str, dstSimulink: str, _: AsnReal, __: AST_Leaftypes, ___: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
316
317
        return ["%s = %s;\n" % (dstSimulink, srcVar)]

318
    def MapBoolean(self, srcVar: str, dstSimulink: str, _: AsnBool, __: AST_Leaftypes, ___: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
319
320
        return ["%s = %s;\n" % (dstSimulink, srcVar)]

321
    def MapOctetString(self, srcVar: str, dstSimulink: str, node: AsnOctetString, _: AST_Leaftypes, __: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
322
        if not node._range:
323
            panicWithCallStack("OCTET STRING (in %s) must have a SIZE constraint inside ASN.1,\nor else we can't generate C code!" % node.Location())  # pragma: no cover
Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
324
        lines = []  # type: List[str]
325
326
        for i in range(0, node._range[-1]):
            lines.append("if (%s.length >= %d) %s.element_data[%d] = %s.value[%d]; else %s.element_data[%d] = 0;\n" %
327
                         (srcVar, i + 1, dstSimulink, i, srcVar, i, dstSimulink, i))
328
        if len(node._range) > 1 and node._range[0] != node._range[1]:
329
330
331
            lines.append("%s.length = %s.length;" % (dstSimulink, srcVar))
        return lines

332
    def MapEnumerated(self, srcVar: str, dstSimulink: str, node: AsnEnumerated, __: AST_Leaftypes, ___: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
333
334
335
336
        if None in [x[1] for x in node._members]:
            panicWithCallStack("an ENUMERATED must have integer values! (%s)" % node.Location())  # pragma: no cover
        return ["%s = %s;\n" % (dstSimulink, srcVar)]

337
    def MapSequence(self, srcVar: str, dstSimulink: str, node: AsnSequenceOrSet, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
338
        lines = []  # type: List[str]
339
340
341
342
343
344
345
346
347
348
        for child in node._members:
            lines.extend(
                self.Map(
                    srcVar + "." + self.CleanName(child[0]),
                    "%s.%s" % (dstSimulink, self.CleanName(child[0])),
                    child[1],
                    leafTypeDict,
                    names))
        return lines

349
    def MapSet(self, srcVar: str, dstSimulink: str, node: AsnSequenceOrSet, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
350
351
        return self.MapSequence(srcVar, dstSimulink, node, leafTypeDict, names)  # pragma: nocover

352
    def MapChoice(self, srcVar: str, dstSimulink: str, node: AsnChoice, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
353
        lines = []  # type: List[str]
354
355
356
357
        childNo = 0
        for child in node._members:
            childNo += 1
            lines.append("%sif (%s.choice == OSS_%s_chosen) {\n" % (self.maybeElse(childNo), srcVar, self.CleanName(child[0])))
358
            lines.extend(
359
                ['    ' + x
360
361
362
363
364
365
                 for x in self.Map(
                     srcVar + ".u." + self.CleanName(child[0]),
                     "%s.%s" % (dstSimulink, self.CleanName(child[0])),
                     child[1],
                     leafTypeDict,
                     names)])
366
367
368
369
            lines.append("    %s.choiceIdx = %d;\n" % (dstSimulink, childNo))
            lines.append("}\n")
        return lines

370
    def MapSequenceOf(self, srcVar: str, dstSimulink: str, node: AsnSequenceOrSetOf, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
371
        if not node._range:
372
373
            panicWithCallStack("(%s) needs a SIZE constraint or else we can't generate C code!\n" % node.Location())  # pragma: no cover
        isMappedToPrimitive = IsElementMappedToPrimitive(node, names)
Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
374
        lines = []  # type: List[str]
375
376
377
        for i in range(0, node._range[-1]):
            lines.extend(self.Map(
                srcVar + ".value[%d]" % i,
378
                ("%s.element_data[%d]" % (dstSimulink, i)) if isMappedToPrimitive else ("%s.element_%02d" % (dstSimulink, i)),
379
380
381
                node._containedType,
                leafTypeDict,
                names))
382
        if len(node._range) > 1 and node._range[0] != node._range[1]:
383
384
385
            lines.append("%s.length = %s.count;\n" % (dstSimulink, srcVar))
        return lines

386
    def MapSetOf(self, srcVar: str, dstSimulink: str, node: AsnSequenceOrSetOf, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> List[str]:  # pylint: disable=invalid-sequence-index
387
388
389
390
        return self.MapSequenceOf(srcVar, dstSimulink, node, leafTypeDict, names)  # pragma: nocover


class SimulinkGlueGenerator(SynchronousToolGlueGenerator):
Thanassis Tsiodras's avatar
Thanassis Tsiodras committed
391
    g_FVname = None  # type: str
392

393
    def Version(self) -> None:
394
395
        print("Code generator: " + "$Id: simulink_B_mapper.py 2390 2012-07-19 12:39:17Z ttsiodras $")  # pragma: no cover

396
    def FromToolToASN1SCC(self) -> RecursiveMapper:
397
398
        return FromSimulinkToASN1SCC()

399
    def FromToolToOSS(self) -> RecursiveMapper:
400
401
        return FromSimulinkToOSS()

402
    def FromASN1SCCtoTool(self) -> RecursiveMapper:
403
404
        return FromASN1SCCtoSimulink()

405
    def FromOSStoTool(self) -> RecursiveMapper:
406
407
        return FromOSStoSimulink()

408
    def HeadersOnStartup(self, unused_modelingLanguage: str, unused_asnFile: str, subProgram: ApLevelContainer, unused_subProgramImplementation: str, unused_outputDir: str, unused_maybeFVname: str) -> None:
409
410
411
412
413
414
415
416
417
        if self.useOSS:
            self.C_SourceFile.write(
                "#include \"%s.oss.h\" // OSS generated\n" % self.asn_name)
            self.C_SourceFile.write("extern OssGlobal *g_world;\n\n")
        self.C_SourceFile.write("#include \"%s.h\" // Space certified compiler generated\n" % self.asn_name)
        self.C_SourceFile.write("#include \"%s.h\"\n\n" % self.CleanNameAsToolWants(subProgram._id))
        self.C_SourceFile.write("#include \"%s_types.h\"\n\n" % self.CleanNameAsToolWants(subProgram._id))
        self.g_FVname = subProgram._id

418
419
420
421
422
423
424
425
426
    def SourceVar(self,
                  unused_nodeTypename: str,
                  unused_encoding: str,
                  unused_node: AsnNode,
                  unused_subProgram: ApLevelContainer,
                  unused_subProgramImplementation: str,
                  param: Param,
                  unused_leafTypeDict: AST_Leaftypes,
                  unused_names: AST_Lookup) -> str:
427
428
429
430
431
432
433
434
        if isinstance(param._sourceElement, AadlPort):
            srcSimulink = "%s_Y.%s" % (self.g_FVname, param._id)  # pragma: no cover
        elif isinstance(param._sourceElement, AadlParameter):
            srcSimulink = "%s_Y.%s" % (self.g_FVname, param._id)
        else:  # pragma: no cover
            panicWithCallStack("%s not supported (yet?)\n" % str(param._sourceElement))  # pragma: no cover
        return srcSimulink

435
436
437
438
439
440
441
442
443
    def TargetVar(self,
                  unused_nodeTypename: str,
                  unused_encoding: str,
                  unused_node: AsnNode,
                  unused_subProgram: ApLevelContainer,
                  unused_subProgramImplementation: str,
                  param: Param,
                  unused_leafTypeDict: AST_Leaftypes,
                  unused_names: AST_Lookup) -> str:
444
445
446
447
448
449
450
451
        if isinstance(param._sourceElement, AadlPort):
            dstSimulink = "%s_U.%s" % (self.g_FVname, param._id)  # pragma: no cover
        elif isinstance(param._sourceElement, AadlParameter):
            dstSimulink = "%s_U.%s" % (self.g_FVname, param._id)
        else:  # pragma: no cover
            panicWithCallStack("%s not supported (yet?)\n" % str(param._sourceElement))  # pragma: no cover
        return dstSimulink

452
    def InitializeBlock(self, unused_modelingLanguage: str, unused_asnFile: str, sp: ApLevelContainer, unused_subProgramImplementation: str, maybeFVname: str) -> None:
453
454
455
        self.C_SourceFile.write("    static int initialized = 0;\n")
        self.C_SourceFile.write("    if (!initialized) {\n")
        self.C_SourceFile.write("        initialized = 1;\n")
456
        self.C_SourceFile.write("        %s_initialize();\n" % self.g_FVname)
457
        # If there are HW(FPGA) configurations defined, initialize also the HW side (the device driver: <self.g_FVname>_Simulink.vhdl.c).
458
        if sp._fpgaConfigurations is not '':
459
            self.C_SourceFile.write("        init_%s_Fpga();\n" % maybeFVname)
460
461
        self.C_SourceFile.write("    }\n")

462
    def ExecuteBlock(self, unused_modelingLanguage: str, unused_asnFile: str, unused_sp: ApLevelContainer, unused_subProgramImplementation: str, unused_maybeFVname: str) -> None:
463
464
465
466
467
468
469
470
471
472
473
        self.C_SourceFile.write("#ifndef rtmGetStopRequested\n")
        self.C_SourceFile.write("    %s_step();\n" % self.g_FVname)
        self.C_SourceFile.write("#else\n")
        self.C_SourceFile.write("    if (!rtmGetStopRequested(%s_M)) {\n" % self.g_FVname)
        self.C_SourceFile.write("        %s_step();\n" % self.g_FVname)
        self.C_SourceFile.write("        if (rtmGetStopRequested(%s_M)) { %s_terminate(); }\n" %
                                (self.g_FVname, self.g_FVname))
        self.C_SourceFile.write("    }\n")
        self.C_SourceFile.write("#endif\n")


474
def OnStartup(modelingLanguage: str, asnFile: str, subProgram: ApLevelContainer, subProgramImplementation: str, outputDir: str, maybeFVname: str, useOSS: bool) -> None:
475
476
477
478
479
    global simulinkBackend
    simulinkBackend = SimulinkGlueGenerator()
    simulinkBackend.OnStartup(modelingLanguage, asnFile, subProgram, subProgramImplementation, outputDir, maybeFVname, useOSS)


480
def OnBasic(nodeTypename: str, node: AsnNode, subProgram: ApLevelContainer, subProgramImplementation: str, param: Param, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> None:
481
482
483
    simulinkBackend.OnBasic(nodeTypename, node, subProgram, subProgramImplementation, param, leafTypeDict, names)


484
def OnSequence(nodeTypename: str, node: AsnNode, subProgram: ApLevelContainer, subProgramImplementation: str, param: Param, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> None:
485
486
487
    simulinkBackend.OnSequence(nodeTypename, node, subProgram, subProgramImplementation, param, leafTypeDict, names)


488
def OnSet(nodeTypename: str, node: AsnNode, subProgram: ApLevelContainer, subProgramImplementation: str, param: Param, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> None:
489
490
491
    simulinkBackend.OnSet(nodeTypename, node, subProgram, subProgramImplementation, param, leafTypeDict, names)  # pragma: nocover


492
def OnEnumerated(nodeTypename: str, node: AsnNode, subProgram: ApLevelContainer, subProgramImplementation: str, param: Param, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> None:
493
494
495
    simulinkBackend.OnEnumerated(nodeTypename, node, subProgram, subProgramImplementation, param, leafTypeDict, names)


496
def OnSequenceOf(nodeTypename: str, node: AsnNode, subProgram: ApLevelContainer, subProgramImplementation: str, param: Param, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> None:
497
498
499
    simulinkBackend.OnSequenceOf(nodeTypename, node, subProgram, subProgramImplementation, param, leafTypeDict, names)


500
def OnSetOf(nodeTypename: str, node: AsnNode, subProgram: ApLevelContainer, subProgramImplementation: str, param: Param, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> None:
501
502
503
    simulinkBackend.OnSetOf(nodeTypename, node, subProgram, subProgramImplementation, param, leafTypeDict, names)  # pragma: nocover


504
def OnChoice(nodeTypename: str, node: AsnNode, subProgram: ApLevelContainer, subProgramImplementation: str, param: Param, leafTypeDict: AST_Leaftypes, names: AST_Lookup) -> None:
505
506
507
    simulinkBackend.OnChoice(nodeTypename, node, subProgram, subProgramImplementation, param, leafTypeDict, names)


508
def OnShutdown(modelingLanguage: str, asnFile: str, sp: ApLevelContainer, subProgramImplementation: str, maybeFVname: str) -> None:
509
    simulinkBackend.OnShutdown(modelingLanguage, asnFile, sp, subProgramImplementation, maybeFVname)