Commit 07c36209 authored by Maxime Perrotin's avatar Maxime Perrotin
Browse files

Merge branch 'feature_buster' of https://gitrepos.estec.esa.int/taste/dmt into feature_buster

parents 7b0a98b0 2d0421ca
Pipeline #4320 passed with stage
in 3 minutes and 11 seconds
......@@ -109,11 +109,10 @@ def OnStartup(unused_modelingLanguage: str, asnFile: str, outputDir: str, badTyp
g_outputGetSetC.write('BitStream *CreateStream(size_t bufferSize) {\n')
g_outputGetSetC.write(' BitStream *pBitStrm = malloc(sizeof(BitStream));\n')
g_outputGetSetC.write(' assert(pBitStrm);\n')
g_outputGetSetC.write(' pBitStrm->buf = malloc(bufferSize);\n')
g_outputGetSetC.write(' assert(pBitStrm->buf);\n')
g_outputGetSetC.write(' pBitStrm->count = bufferSize;\n')
g_outputGetSetC.write(' memset(pBitStrm->buf, 0x0, bufferSize);\n')
g_outputGetSetC.write(' ResetStream(pBitStrm);\n')
g_outputGetSetC.write(' unsigned char* buf = malloc(bufferSize);\n')
g_outputGetSetC.write(' assert(buf);\n')
g_outputGetSetC.write(' memset(buf, 0x0, bufferSize);\n')
g_outputGetSetC.write(' BitStream_Init(pBitStrm, buf, bufferSize);\n')
g_outputGetSetC.write(' return pBitStrm;\n')
g_outputGetSetC.write('}\n\n')
g_outputGetSetC.write('void DestroyStream(BitStream *pBitStrm) {\n')
......
......@@ -409,10 +409,9 @@ class QGenCGlueGenerator(SynchronousToolGlueGenerator):
"#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).lower())
self.C_SourceFile.write("#include \"%s_types.h\"\n\n" % self.CleanNameAsToolWants(subProgram._id).lower())
self.C_SourceFile.write("static comp_Input cInput;\n\n")
self.C_SourceFile.write("static comp_Output cOutput;\n\n")
self.C_SourceFile.write("#include \"qgen_entry_%s.h\"\n\n" % self.CleanNameAsToolWants(subProgram._id).lower())
self.C_SourceFile.write("static qgen_entry_%s_comp_Input cInput;\n\n" % self.CleanNameAsToolWants(subProgram._id))
self.C_SourceFile.write("static qgen_entry_%s_comp_Output cOutput;\n\n" % self.CleanNameAsToolWants(subProgram._id))
self.g_FVname = subProgram._id
def SourceVar(self,
......@@ -453,19 +452,11 @@ class QGenCGlueGenerator(SynchronousToolGlueGenerator):
self.C_SourceFile.write(" static int initialized = 0;\n")
self.C_SourceFile.write(" if (!initialized) {\n")
self.C_SourceFile.write(" initialized = 1;\n")
self.C_SourceFile.write(" %s_init();\n" % self.g_FVname)
self.C_SourceFile.write(" qgen_entry_%s_init();\n" % self.g_FVname)
self.C_SourceFile.write(" }\n")
def ExecuteBlock(self, unused_modelingLanguage: str, unused_asnFile: str, unused_sp: ApLevelContainer, unused_subProgramImplementation: str, unused_maybeFVname: str) -> None:
self.C_SourceFile.write("#ifndef rtmGetStopRequested\n")
self.C_SourceFile.write(" %s_comp(&cInput, &cOutput);\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(&cInput, &cOutput);\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")
self.C_SourceFile.write(" qgen_entry_%s_comp(&cInput, &cOutput);\n" % self.g_FVname)
qgencBackend: QGenCGlueGenerator
......
......@@ -149,15 +149,11 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
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('with qgen_entry_%s;\n' % self.CleanNameAsADAWants(subProgram._id))
self.ADA_SourceFile.write(
'package body %s is\n\n' %
self.CleanNameAsADAWants(subProgram._id + "_" + subProgramImplementation + "_wrapper"))
......@@ -267,6 +263,41 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
self.ADA_SourceFile.write(
" end Ada_%s;\n\n" % tmpSpName)
elif subProgramImplementation == "QGenC":
self.C_HeaderFile.write(
"int %s%s(void *pBuffer);\n" % (tmpSpName, fpgaSuffix))
self.ADA_HeaderFile.write(
"procedure Ada_%s(pBuffer : in Interfaces.C.char_array);\n" % tmpSpName)
self.ADA_SourceFile.write(
"procedure Ada_%s(pBuffer : in Interfaces.C.char_array) is\n" % tmpSpName)
self.ADA_SourceFile.write(
" function C_%s(pBuffer : Interfaces.C.char_array) return 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);\n' % tmpSpName)
self.ADA_SourceFile.write(
"end Ada_%s;\n\n" % tmpSpName)
self.C_SourceFile.write(
"int %s%s(void *pBuffer)\n{\n" % (tmpSpName, fpgaSuffix))
self.C_SourceFile.write(
" STATIC asn1Scc%s var_%s;\n" %
(self.CleanNameAsToolWants(nodeTypename), self.CleanNameAsToolWants(nodeTypename)))
toolToAsn1 = self.FromToolToASN1SCC() # pylint: disable=assignment-from-no-return
lines = toolToAsn1.Map(
srcVar,
"var_" + self.CleanNameAsToolWants(nodeTypename),
node,
leafTypeDict,
names) if toolToAsn1 else []
lines = [" " + x for x in lines]
self.C_SourceFile.write("".join(lines))
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")
else:
self.C_HeaderFile.write(
"int %s%s(void *pBuffer, size_t iMaxBufferSize);\n" % (tmpSpName, fpgaSuffix))
......@@ -404,6 +435,42 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
self.ADA_SourceFile.write(
" end Ada_%s;\n\n" % tmpSpName)
elif subProgramImplementation == "QGenC":
self.C_HeaderFile.write(
"int %s%s(void *pBuffer);\n" % (tmpSpName, fpgaSuffix))
self.ADA_HeaderFile.write(
"procedure Ada_%s(pBuffer : Interfaces.C.char_array);\n" % tmpSpName)
self.ADA_SourceFile.write(
"procedure Ada_%s(pBuffer : Interfaces.C.char_array) is\n" % tmpSpName)
self.ADA_SourceFile.write(
" procedure C_%s(pBuffer : Interfaces.C.char_array);\n" % tmpSpName)
self.ADA_SourceFile.write(
' pragma Import(C, C_%s, "%s");\n' % (tmpSpName, tmpSpName))
self.ADA_SourceFile.write(
'begin\n'
' C_%s(pBuffer);\n' % tmpSpName)
self.ADA_SourceFile.write(
"end Ada_%s;\n\n" % tmpSpName)
self.C_SourceFile.write(
"int %s%s(void *pBuffer)\n{\n" % (tmpSpName, fpgaSuffix))
self.C_SourceFile.write(" STATIC asn1Scc%s var_%s;\n" %
(self.CleanNameAsToolWants(nodeTypename), self.CleanNameAsToolWants(nodeTypename)))
self.C_SourceFile.write(" var_%s = *(asn1Scc%s *) pBuffer;\n {\n" %
(self.CleanNameAsToolWants(nodeTypename),
self.CleanNameAsToolWants(nodeTypename)))
asn1ToTool = self.FromASN1SCCtoTool() # pylint: disable=assignment-from-no-return
lines = asn1ToTool.Map(
"var_" + self.CleanNameAsToolWants(nodeTypename),
targetVar,
node,
leafTypeDict,
names) if asn1ToTool else []
lines = [" " + x for x in lines]
self.C_SourceFile.write("".join(lines))
self.C_SourceFile.write(" return 0;\n")
self.C_SourceFile.write(" }\n")
self.C_SourceFile.write("}\n\n")
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
......@@ -580,7 +647,7 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
self.CleanNameAsToolWants(param._id),
self.CleanNameAsToolWants(param._id)))
self.ADA_SourceFile.write("\n %s.comp (" % self.CleanNameAsADAWants(sp._id))
self.ADA_SourceFile.write("\n qgen_entry_%s.comp (" % self.CleanNameAsADAWants(sp._id))
for param in sp._params:
if param._id != sp._params[0]._id:
self.ADA_SourceFile.write(', ')
......@@ -624,22 +691,34 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
self.C_HeaderFile.write("void Execute_%s(void);\n" % self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation))
if maybeFVname != "":
if not (genFpgaDevDrv and maybeFVname in fpga_seen and fpga_seen[maybeFVname] == 'with_init_already'):
self.C_HeaderFile.write("void init_%s%s(void);\n" % (self.CleanNameAsADAWants(maybeFVname), fpgaSuffix))
if modelingLanguage == "QGenC":
self.C_HeaderFile.write("void %s_PI_%s_startup(void);\n" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id)))
else:
self.C_HeaderFile.write("void init_%s%s(void);\n" % (self.CleanNameAsADAWants(maybeFVname), fpgaSuffix))
if genFpgaDevDrv:
# Return to dispatcher if HW delegation via Execute() is successful (0) or not (-1).
self.C_HeaderFile.write("int %s_%s%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id), fpgaSuffix))
else:
self.C_HeaderFile.write("void %s_%s%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id), fpgaSuffix))
if modelingLanguage == "QGenC":
self.C_HeaderFile.write("void %s_PI_%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id)))
else:
self.C_HeaderFile.write("void %s_%s%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id), fpgaSuffix))
else: # pragma: no cover
self.C_HeaderFile.write("void %s_init%s(void);\n" % (self.CleanNameAsADAWants(sp._id), fpgaSuffix)) # pragma: no cover
self.C_HeaderFile.write("void %s%s(" % (self.CleanNameAsADAWants(sp._id), fpgaSuffix)) # pragma: no cover
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))
if modelingLanguage == "QGenC":
if isinstance(param, InParam):
self.C_HeaderFile.write('void *p' + self.CleanNameAsToolWants(param._id))
else:
self.C_HeaderFile.write('void *p' + self.CleanNameAsToolWants(param._id))
else:
self.C_HeaderFile.write('void *p' + self.CleanNameAsToolWants(param._id) + ', size_t *pSize_' + self.CleanNameAsToolWants(param._id))
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")
# Check if Function Block will exist both as SW and HW. If yes generate dispatcher function (to delegate to SW or HW).
......@@ -672,7 +751,10 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
if maybeFVname != "":
if not (genFpgaDevDrv and maybeFVname in fpga_seen and fpga_seen[maybeFVname] == 'with_init_already'):
self.C_SourceFile.write("void init_%s%s(void)\n" % (self.CleanNameAsADAWants(maybeFVname), fpgaSuffix))
if modelingLanguage == "QGenC":
self.C_SourceFile.write("void %s_PI_%s_startup(void)\n" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id)))
else:
self.C_SourceFile.write("void init_%s%s(void)\n" % (self.CleanNameAsADAWants(maybeFVname), fpgaSuffix))
else: # pragma: no cover
self.C_SourceFile.write("void %s_init(void)\n" % self.CleanNameAsADAWants(sp._id)) # pragma: no cover
if not (genFpgaDevDrv and maybeFVname in fpga_seen and fpga_seen[maybeFVname] == 'with_init_already'):
......@@ -687,16 +769,25 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
# Return to dispatcher if HW delegation via Execute() is successful (0) or not (-1).
self.C_SourceFile.write("int %s_%s%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id), fpgaSuffix))
else:
self.C_SourceFile.write("void %s_%s%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id), fpgaSuffix))
if modelingLanguage == "QGenC":
self.C_SourceFile.write("void %s_PI_%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id)))
else:
self.C_SourceFile.write("void %s_%s%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id), fpgaSuffix))
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))
if modelingLanguage == "QGenC":
if isinstance(param, InParam):
self.C_SourceFile.write('void *p' + self.CleanNameAsToolWants(param._id))
else:
self.C_SourceFile.write('void *p' + self.CleanNameAsToolWants(param._id))
else:
self.C_SourceFile.write('void *p' + self.CleanNameAsToolWants(param._id) + ', size_t *pSize_' + self.CleanNameAsToolWants(param._id))
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")
# Call Dispatcher function
......@@ -742,15 +833,25 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
self.CleanNameAsADAWants(param._id),
fpgaSuffix)
if isinstance(param, InParam):
self.C_SourceFile.write(' %s(p%s, size_%s);\n' %
(tmpSpName,
self.CleanNameAsToolWants(param._id),
self.CleanNameAsToolWants(param._id)))
if modelingLanguage == "QGenC":
self.C_SourceFile.write(' %s(p%s);\n' %
(tmpSpName,
self.CleanNameAsToolWants(param._id)))
else:
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
if modelingLanguage == "QGenC":
self.C_SourceFile.write(' %s(p%s);\n' %
(tmpSpName,
self.CleanNameAsToolWants(param._id)))
else:
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
if genFpgaDevDrv:
......@@ -770,11 +871,16 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
param._id,
fpgaSuffix)
if isinstance(param, (InOutParam, OutParam)):
self.C_SourceFile.write(' *pSize_%s = %s(p%s, %s);\n' %
(self.CleanNameAsToolWants(param._id),
tmpSpName,
self.CleanNameAsToolWants(param._id),
param._signal._asnSize))
if modelingLanguage == "QGenC":
self.C_SourceFile.write(' %s(p%s);\n' %
(tmpSpName,
self.CleanNameAsToolWants(param._id)))
else:
self.C_SourceFile.write(' *pSize_%s = %s(p%s, %s);\n' %
(self.CleanNameAsToolWants(param._id),
tmpSpName,
self.CleanNameAsToolWants(param._id),
param._signal._asnSize))
if genFpgaDevDrv:
# HW delegation via Execute() was successful, so return 0 to Dispatcher
self.C_SourceFile.write(" return 0;\n")
......
......@@ -141,7 +141,7 @@ g_sync_mappers = {
'Simulink': simulink_B_mapper,
'gui': gui_B_mapper,
'python': python_B_mapper,
'QgenC': qgenc_B_mapper,
'QGenC': qgenc_B_mapper,
'vhdl': vhdl_B_mapper,
}
......
......@@ -401,41 +401,41 @@ def ParseAsnFileList(listOfFilenames: List[str]) -> None: # pylint: disable=inv
utility.panic(
"The configured cache folder:\n\n\t" + projectCache + "\n\n...is not there!\n")
# To avoid race conditions from multiple processes spawning ASN1SCC at the same time,
# enforce mutual exclusion via locking.
with lock_filename('/tmp/onlyOneASN1SCC', verbose=False):
xmlAST = None
someFilesHaveChanged = False
if projectCache is not None:
filehash = hashlib.md5()
for each in sorted(listOfFilenames):
filehash.update(
open(each, "r", encoding="utf-8").read().encode('utf-8'))
# also hash the file path: it is used in the AST in XML, so it is
# not enough to hash the content of the ASN.1 files, as two sets
# of files may have the same hash, that would lead to different XML
# content.
filehash.update(each.encode('utf-8'))
newHash = filehash.hexdigest()
# set the name of the XML files containing the dumped ASTs
xmlAST = projectCache + os.sep + newHash + "_ast_v4.xml"
xmlAST2 = projectCache + os.sep + newHash + "_ast_v1.xml"
if not os.path.exists(xmlAST) or not os.path.exists(xmlAST2):
someFilesHaveChanged = True
print("[DMT] No cached model found for", ",".join(listOfFilenames))
else:
# no projectCache set, so xmlAST is set to None
# Compute MD5 checksum of the contents of our input ASN.1 files
filehash = hashlib.md5()
for each in sorted(listOfFilenames):
filehash.update(
open(each, "r", encoding="utf-8").read().encode('utf-8'))
# also hash the file path: it is used in the AST in XML, so it is
# not enough to hash the content of the ASN.1 files, as two sets
# of files may have the same hash, that would lead to different XML
# content.
filehash.update(each.encode('utf-8'))
newHash = filehash.hexdigest()
xmlAST = None
someFilesHaveChanged = False
if projectCache is not None:
# set the name of the XML files containing the dumped ASTs
xmlAST = projectCache + os.sep + newHash + "_ast_v4.xml"
if not os.path.exists(xmlAST):
someFilesHaveChanged = True
if not someFilesHaveChanged:
print("[DMT] Reusing cached ASN.1 AST for ", ",".join(listOfFilenames))
print("[DMT] No cached model found for", ",".join(listOfFilenames))
else:
# no projectCache set, so xmlAST is set to None
someFilesHaveChanged = True
if not someFilesHaveChanged:
print("[DMT] Reusing cached ASN.1 AST for ", ",".join(listOfFilenames))
if not xmlAST:
(dummy, xmlAST) = tempfile.mkstemp()
os.fdopen(dummy).close()
if not xmlAST:
(dummy, xmlAST) = tempfile.mkstemp()
os.fdopen(dummy).close()
if someFilesHaveChanged:
# To avoid race conditions from multiple processes spawning ASN1SCC at the same time,
# enforce mutual exclusion via locking.
if someFilesHaveChanged:
with lock_filename('/tmp/onlyOneASN1SCC' + newHash, verbose=False):
asn1SccPath = spawn.find_executable('asn1.exe')
if asn1SccPath is None:
utility.panic("ASN1SCC seems not installed on your system (asn1.exe not found in PATH).\n")
......@@ -453,9 +453,9 @@ def ParseAsnFileList(listOfFilenames: List[str]) -> None: # pylint: disable=inv
utility.panic("ASN1SCC reported usage error. Aborting...")
else:
utility.panic("ASN1SCC generic error. Contact ESA with this input. Aborting...")
ParseASN1SCC_AST(xmlAST)
if projectCache is None:
os.unlink(xmlAST)
ParseASN1SCC_AST(xmlAST)
if projectCache is None:
os.unlink(xmlAST)
def Dump() -> None:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment