Commit 618162af authored by Tiago Jorge's avatar Tiago Jorge
Browse files

Add doc comments for some CoRA changes under dmt

parent f5d0f92e
...@@ -454,6 +454,7 @@ class SimulinkGlueGenerator(SynchronousToolGlueGenerator): ...@@ -454,6 +454,7 @@ class SimulinkGlueGenerator(SynchronousToolGlueGenerator):
self.C_SourceFile.write(" if (!initialized) {\n") self.C_SourceFile.write(" if (!initialized) {\n")
self.C_SourceFile.write(" initialized = 1;\n") self.C_SourceFile.write(" initialized = 1;\n")
self.C_SourceFile.write(" %s_initialize(1);\n" % self.g_FVname) self.C_SourceFile.write(" %s_initialize(1);\n" % self.g_FVname)
# If there are HW(FPGA) configurations defined, initialize also the HW side (the device driver: <self.g_FVname>_Simulink.vhdl.c).
if sp._fpgaConfigurations is not '': if sp._fpgaConfigurations is not '':
self.C_SourceFile.write(" init_%s_Brave_Fpga();\n" % maybeFVname) self.C_SourceFile.write(" init_%s_Brave_Fpga();\n" % maybeFVname)
self.C_SourceFile.write(" }\n") self.C_SourceFile.write(" }\n")
......
...@@ -37,8 +37,15 @@ TSource = TypeVar('TSource') ...@@ -37,8 +37,15 @@ TSource = TypeVar('TSource')
TDestin = TypeVar('TDestin') TDestin = TypeVar('TDestin')
brave_seen = {} brave_seen = {}
# Add suffix to generated FPGA device driver's (<PI name>_<Language>.vhdl.c) functions to avoid multiple definition errors (conflict with "vm_if")
fpgaSuffix = '' fpgaSuffix = ''
# 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
dispatcherSuffix = "_Brave_Dispatch" dispatcherSuffix = "_Brave_Dispatch"
# 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)
genHwDevDrv = False genHwDevDrv = False
class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]): class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
...@@ -109,12 +116,17 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]): ...@@ -109,12 +116,17 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
outputDir: str, outputDir: str,
maybeFVname: str, maybeFVname: str,
useOSS: bool) -> None: useOSS: bool) -> None:
# 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
global genHwDevDrv global genHwDevDrv
# Add suffix to generated FPGA device driver's functions to avoid multiple definition errors (conflict with "vm_if")
global fpgaSuffix global fpgaSuffix
genHwDevDrv = subProgram._fpgaConfigurations is not '' and ((subProgramImplementation.lower() == "c" or subProgramImplementation.lower() == "simulink") and modelingLanguage == "vhdl"); genHwDevDrv = subProgram._fpgaConfigurations is not '' and ((subProgramImplementation.lower() == "c" or subProgramImplementation.lower() == "simulink") and modelingLanguage == "vhdl");
if genHwDevDrv: if genHwDevDrv:
fpgaSuffix = "_Brave_Fpga" fpgaSuffix = "_Brave_Fpga"
else: else:
# To avoid code duplication, use suffix anyway but as an empty string when not to be applied
fpgaSuffix = '' fpgaSuffix = ''
if modelingLanguage == "QGenAda": if modelingLanguage == "QGenAda":
...@@ -525,7 +537,6 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]): ...@@ -525,7 +537,6 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
self.Common(nodeTypename, node, subProgram, subProgramImplementation, param, leafTypeDict, names) self.Common(nodeTypename, node, subProgram, subProgramImplementation, param, leafTypeDict, names)
def OnShutdown(self, modelingLanguage: str, asnFile: str, sp: ApLevelContainer, subProgramImplementation: str, maybeFVname: str) -> None: def OnShutdown(self, modelingLanguage: str, asnFile: str, sp: ApLevelContainer, subProgramImplementation: str, maybeFVname: str) -> None:
# Check if Function Block will exist both as SW and HW
global genHwDevDrv global genHwDevDrv
global fpgaSuffix global fpgaSuffix
global dispatcherSuffix global dispatcherSuffix
...@@ -591,7 +602,6 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]): ...@@ -591,7 +602,6 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation + "_wrapper")) self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation + "_wrapper"))
else: else:
# Check if Function Block will exist both as SW and HW. If yes append suffix to avoid multiple definition errors.
if genHwDevDrv: if genHwDevDrv:
if maybeFVname not in brave_seen: if maybeFVname not in brave_seen:
brave_seen[maybeFVname] = 'no_init_yet'; brave_seen[maybeFVname] = 'no_init_yet';
...@@ -622,6 +632,9 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]): ...@@ -622,6 +632,9 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
self.C_HeaderFile.write(");\n") 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). # Check if Function Block will exist both as SW and HW. If yes generate dispatcher function (to delegate to SW or HW).
# 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
if genHwDevDrv: if genHwDevDrv:
if maybeFVname != "": if maybeFVname != "":
self.C_HeaderFile.write("int %s_%s%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id), dispatcherSuffix)) self.C_HeaderFile.write("int %s_%s%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id), dispatcherSuffix))
...@@ -673,6 +686,15 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]): ...@@ -673,6 +686,15 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
self.C_SourceFile.write('void *p' + self.CleanNameAsToolWants(param._id) + ', size_t *pSize_' + self.CleanNameAsToolWants(param._id)) self.C_SourceFile.write('void *p' + self.CleanNameAsToolWants(param._id) + ', size_t *pSize_' + self.CleanNameAsToolWants(param._id))
self.C_SourceFile.write(")\n{\n") self.C_SourceFile.write(")\n{\n")
# 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
if sp._fpgaConfigurations is not '' and subProgramImplementation.lower() == "simulink" and modelingLanguage != "vhdl": 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(' // Calling Brave VHDL dispatcher function\n')
self.C_SourceFile.write(' if (0 == %s_%s%s (' % \ self.C_SourceFile.write(' if (0 == %s_%s%s (' % \
...@@ -743,6 +765,9 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]): ...@@ -743,6 +765,9 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
self.C_SourceFile.write("}\n\n") self.C_SourceFile.write("}\n\n")
# Check if Function Block will exist both as SW and HW. If yes generate dispatcher function (to delegate to SW or HW). # Check if Function Block will exist both as SW and HW. If yes generate dispatcher function (to delegate to SW or HW).
# 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
if genHwDevDrv: if genHwDevDrv:
if maybeFVname != "": if maybeFVname != "":
self.C_SourceFile.write("int %s_%s%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id), dispatcherSuffix)) self.C_SourceFile.write("int %s_%s%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id), dispatcherSuffix))
......
...@@ -391,10 +391,13 @@ def ProcessCustomBackends( ...@@ -391,10 +391,13 @@ def ProcessCustomBackends(
else: else:
panic("Unexpected call of getCustomBackends...") # pragma: no cover panic("Unexpected call of getCustomBackends...") # pragma: no cover
# Add call to the VHDL B-mapper also for C and Simulink functions (x[2]) with FPGA configuration(s) defined (x[4])
for si in [x for x in SystemsAndImplementations if x[2] is not None and (x[2].lower() in ["gui_ri", "gui_pi", "vhdl"] or ((x[2].lower() == "c" or x[2].lower() == "simulink") and len(x)>4 and x[4] is not ''))]: for si in [x for x in SystemsAndImplementations if x[2] is not None and (x[2].lower() in ["gui_ri", "gui_pi", "vhdl"] or ((x[2].lower() == "c" or x[2].lower() == "simulink") and len(x)>4 and x[4] is not ''))]:
# We do, start the work # We do, start the work
spName, sp_impl, lang, maybeFVname = si[0], si[1], si[2], si[3] spName, sp_impl, lang, maybeFVname = si[0], si[1], si[2], si[3]
# Add call to the VHDL B-mapper also for C and Simulink functions (si[2]) with FPGA configuration(s) defined (si[4])
if (si[2].lower() == "c" or si[2].lower() == "simulink") and len(si)>4 and si[4] is not '': if (si[2].lower() == "c" or si[2].lower() == "simulink") and len(si)>4 and si[4] is not '':
# pretend its VHDL
lang = "vhdl" lang = "vhdl"
sp = commonPy.aadlAST.g_apLevelContainers[spName] sp = commonPy.aadlAST.g_apLevelContainers[spName]
if len(sp._params) == 0: if len(sp._params) == 0:
......
...@@ -1251,6 +1251,7 @@ class Parser(antlr.LLkParser): ...@@ -1251,6 +1251,7 @@ class Parser(antlr.LLkParser):
if not g_apLevelContainers.has_key(typeid.getText()): if not g_apLevelContainers.has_key(typeid.getText()):
panic("Line %d: Subprogram (%s) must first be declared before it is implemented" % (typeid.getLine(), typeid.getText())) panic("Line %d: Subprogram (%s) must first be declared before it is implemented" % (typeid.getLine(), typeid.getText()))
sp = g_apLevelContainers[typeid.getText()] sp = g_apLevelContainers[typeid.getText()]
# Add field for FPGA configurations
g_subProgramImplementations.append([typeid.getText(), defid.getText(), sp._language, "", sp._fpgaConfigurations]) g_subProgramImplementations.append([typeid.getText(), defid.getText(), sp._language, "", sp._fpgaConfigurations])
la1 = self.LA(1) la1 = self.LA(1)
if False: if False:
...@@ -1330,6 +1331,7 @@ class Parser(antlr.LLkParser): ...@@ -1330,6 +1331,7 @@ class Parser(antlr.LLkParser):
stripQuotes = assoc._value.replace("\"", "") stripQuotes = assoc._value.replace("\"", "")
#sp.SetLanguage(stripQuotes) #sp.SetLanguage(stripQuotes)
g_subProgramImplementations[-1][3] = stripQuotes g_subProgramImplementations[-1][3] = stripQuotes
# Assign defined FPGA configurations
if assoc._name[-19:].lower() == "fpga_configurations": if assoc._name[-19:].lower() == "fpga_configurations":
stripQuotes = assoc._value.replace("\"", "") stripQuotes = assoc._value.replace("\"", "")
g_subProgramImplementations[-1][4] = stripQuotes g_subProgramImplementations[-1][4] = stripQuotes
......
...@@ -151,7 +151,7 @@ class ApLevelContainer: ...@@ -151,7 +151,7 @@ class ApLevelContainer:
self._calls = [] self._calls = []
self._params = [] self._params = []
self._connections = [] self._connections = []
self._fpgaConfigurations = '' self._fpgaConfigurations = '' # The configuration(s)/"mode(s)" for which the Function's HW implementation shall apply (execution in FPGA)
self._language = None self._language = None
def AddCalledAPLC(self, idAPLC): def AddCalledAPLC(self, idAPLC):
...@@ -170,6 +170,7 @@ class ApLevelContainer: ...@@ -170,6 +170,7 @@ class ApLevelContainer:
def SetLanguage(self, language): def SetLanguage(self, language):
self._language = language self._language = language
# Assign FPGA configurations
def SetFPGAConfigurations(self, fpgaConfigurations): def SetFPGAConfigurations(self, fpgaConfigurations):
self._fpgaConfigurations = fpgaConfigurations self._fpgaConfigurations = fpgaConfigurations
......
Supports Markdown
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