Commit e0b382ea authored by Tiago Jorge's avatar Tiago Jorge
Browse files

Add further doc comments for some CoRA changes under dmt

parent 618162af
......@@ -447,6 +447,10 @@ class VHDLGlueGenerator(SynchronousToolGlueGeneratorGeneric[List[int], List[int]
#define LOGDEBUG(x...)
#endif
// BRAVE device driver considers different possible FPGA status
// See for instance device drivers' function <Function Block name>_<PI name>_Brave_Fpga (invoked by dispatcher when delegation is to HW)
// and that first checks if FPGA is "ready" before converting parameters and initiating RMAP exchanges with HW
// This status is to be maintained by a dedicated component acting as the FPGA reconfiguration manager and that "watchdogs" the HW component
#define FPGA_READY "ready"
#define FPGA_RECONFIGURING "reconfiguring"
#define FPGA_ERROR "error"
......
......@@ -609,6 +609,7 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
brave_seen[maybeFVname] = 'with_init_already'
if genHwDevDrv:
# Execute() returns if interaction with BRAVE HW is successful, that is, if RMAP write and read commands are successful (0) or not (-1)
self.C_HeaderFile.write("int Execute_%s%s();\n" % (self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation), fpgaSuffix))
else:
self.C_HeaderFile.write("void Execute_%s();\n" % self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation))
......@@ -616,6 +617,7 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
if not (genHwDevDrv and maybeFVname in brave_seen and brave_seen[maybeFVname] is 'with_init_already'):
self.C_HeaderFile.write("void init_%s%s();\n" % (self.CleanNameAsADAWants(maybeFVname), fpgaSuffix))
if genHwDevDrv:
# 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))
......@@ -652,6 +654,7 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
self.C_HeaderFile.write("\n#endif\n")
if genHwDevDrv:
# Execute() returns if interaction with BRAVE HW is successful, that is, if RMAP write and read commands are successful (0) or not (-1)
self.C_SourceFile.write("int Execute_%s%s()\n{\n" % (self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation), fpgaSuffix))
else:
self.C_SourceFile.write("void Execute_%s()\n{\n" % self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation))
......@@ -672,6 +675,7 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
if maybeFVname != "":
if genHwDevDrv:
# 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))
......@@ -693,7 +697,7 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
# 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
# 3) If successfully delegated to HW (returning 0), afterwards 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":
self.C_SourceFile.write(' // Calling Brave VHDL dispatcher function\n')
......@@ -711,6 +715,7 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
self.C_SourceFile.write(")) return;\n")
if genHwDevDrv:
# Check if FPGA is ready before converting parameters and initiating RMAP exchanges with HW
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)))
......@@ -740,6 +745,7 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
# Do functional work
if genHwDevDrv:
# Check if HW delegation via Execute() is successful: return -1 to Dispatcher if not (so SW side can be called as fallback)
self.C_SourceFile.write(" if(Execute_%s%s()) return -1;\n" % (self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation), fpgaSuffix))
else:
self.C_SourceFile.write(" Execute_%s();\n" % self.CleanNameAsADAWants(sp._id + "_" + subProgramImplementation))
......@@ -761,6 +767,7 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
self.CleanNameAsToolWants(param._id),
param._signal._asnSize))
if genHwDevDrv:
# HW delegation via Execute() was successful, so return 0 to Dispatcher
self.C_SourceFile.write(" return 0;\n")
self.C_SourceFile.write("}\n\n")
......@@ -768,6 +775,12 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
# 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
# Detailed description:
# Delegate to one or the other side (SW or HW) depending on whether the value of a global variable storing the current
# configuration (p_szGlobalState) equals one of those configurations listed (fConfigList) for the target Function Block in its respective IV field.
# If so, OR such list defines the "magic" word "AllModes", computation will be delegated to HW/FPGA (<Function Block name>_<PI name><fpgaSuffix> will be called).
# Otherwise, FPGA is not called and computation will proceed in SW through the "usual" SW side/glue counterpart.
# Debug level logs (LOGDEBUG) can be used to track this delegation during testing.
if genHwDevDrv:
if maybeFVname != "":
self.C_SourceFile.write("int %s_%s%s(" % (self.CleanNameAsADAWants(maybeFVname), self.CleanNameAsADAWants(sp._id), dispatcherSuffix))
......@@ -783,7 +796,10 @@ class SynchronousToolGlueGeneratorGeneric(Generic[TSource, TDestin]):
self.C_SourceFile.write(")\n{\n")
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(' configuration (p_szGlobalState) equals one of those configurations listed (fConfigList) for the target Function Block in its respective IV field.\n')
self.C_SourceFile.write(' If so, OR such list defines the "magic" word "AllModes", computation will be delegated to HW/FPGA (<Function Block name>_<PI name><fpgaSuffix> will be called).\n')
self.C_SourceFile.write(' Otherwise, FPGA is not called and computation will proceed in SW through the "usual" SW side/glue counterpart.\n')
self.C_SourceFile.write(' Debug level logs (LOGDEBUG) can be used to track this delegation during testing.\n')
self.C_SourceFile.write(' */\n')
self.C_SourceFile.write(' extern const char p_szGlobalState[];\n')
self.C_SourceFile.write(' char *fConfig;\n')
......
......@@ -100,7 +100,7 @@ from .B_mappers import simulink_B_mapper
from .B_mappers import micropython_async_B_mapper
from .B_mappers import vhdl_B_mapper
from .B_mappers import zestSC1_B_mapper
from .B_mappers import brave_B_mapper
from .B_mappers import brave_B_mapper # Specific CoRA B-mapper for BRAVE
from .B_mappers.module_protos import Sync_B_Mapper, Async_B_Mapper
......@@ -217,6 +217,7 @@ types). This used to cover Dumpable C/Ada Types and OG headers.'''
def getSyncBackend(modelingLanguage: str) -> Sync_B_Mapper:
if modelingLanguage not in g_sync_mappers:
panic("Synchronous modeling language '%s' not supported" % modelingLanguage)
# For VHDL, BRAVE will take precedence in case both BRAVE and ZESTSC1 environment variables are defined
if os.getenv("BRAVE") is not None and modelingLanguage == 'vhdl':
return cast(Sync_B_Mapper, brave_B_mapper)
if os.getenv("ZESTSC1") is not None and modelingLanguage == 'vhdl':
......@@ -382,6 +383,7 @@ def ProcessCustomBackends(
if lang.lower() in ["gui_pi", "gui_ri"]:
return [cast(Sync_B_Mapper, x) for x in [python_B_mapper, pyside_B_mapper]] # pragma: no cover
elif lang.lower() == "vhdl": # pragma: no cover
# For VHDL, BRAVE will take precedence in case both BRAVE and ZESTSC1 environment variables are defined
if os.getenv("BRAVE") is not None:
return [cast(Sync_B_Mapper, brave_B_mapper)] # pragma: no cover
if os.getenv("ZESTSC1") is not None:
......
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