%if EXISTS("_SYSBODLIB_") == TLC_FALSE
%assign _SYSBODLIB_ = TLC_TRUE
%function LibAddToSystem(system, fieldname, value) void
%if ISFIELD(system.InstanceCache, fieldname)
%assign args = ["LibAddToSystem", %<fieldname>]
%<SLibReportErrorWithIdAndArgs("RTW:tlc:DuplicateField", args)>
%else
%addtorecord system.InstanceCache %<fieldname> value
%endif
%endfunction
%function LibSetSystemField(system, fieldname, value) void
%if ISFIELD(system.InstanceCache, fieldname)
%assign prevVal = GETFIELD(system.InstanceCache, fieldname)
%if (TYPE(prevVal) != TYPE(value) || prevVal != value)
%<SETFIELD(system.InstanceCache, fieldname, value)>
%endif
%else
%assign args = ["LibSetSystemField", %<fieldname>]
%<SLibReportErrorWithIdAndArgs("RTW:tlc:FieldNotFound", args)>
%endif
%endfunction
%function LibSetSystemFieldForTID(system, fieldname1, fieldname2, value) void
%assign ListofTIDhasNoEmptyCode =""
%if TYPE(value) == "Vector"
%if SLibPartitionGroupingSystem(system)
%assert SIZE(value, 1) == SLibGetNumPartitions()
%else
%assert SIZE(value, 1) == NumSampleTimes
%endif
%assign numAsyncTasks = LibGetNumAsyncTasks() + SLibGetNumExplictTasksInUnion()
%foreach idx = numAsyncTasks
%assign Tid = idx + NumRuntimeExportedRates
%if SLibPartitionGroupingSystem(system)
%assign content = value[SLibGetNumPartitions() - numAsyncTasks + idx]
%if !WHITE_SPACE(content)
%assign pidVec = SLibGetPidFromTid(Tid)
%assert SIZE(pidVec, 1) == 1
%assign FieldName = "Cached" + fieldname1 + "%<Tid>%" + fieldname2
%assign ListofTIDhasNoEmptyCode = ListofTIDhasNoEmptyCode ...
+ " TID%<Tid>PID% "
%<LibSetSystemField(system, FieldName, content)>
%endif
%else
%if !WHITE_SPACE(value[Tid])
%assign FieldName = "Cached" + fieldname1 + "%<Tid>" + fieldname2
%assign ListofTIDhasNoEmptyCode = ListofTIDhasNoEmptyCode ...
+ " TID%<Tid> "
%<LibSetSystemField(system, FieldName, value[Tid])>
%endif
%endif
%endforeach
%assign fcnType = fieldname1
%if SLibSystemFcnPeriodicRateGrouping(system, fcnType)
%if SLibPartitionGroupingSystem(system)
%assign bufIdx = 0
%foreach Tid = NumRuntimeExportedRates
%assign pidVec = SLibGetPidFromTid(Tid)
%foreach i = SIZE(pidVec, 1)
%if !WHITE_SPACE(value[bufIdx])
%assign FieldName = "Cached" + fieldname1 + "%<Tid>" + "%" + fieldname2
%assign ListofTIDhasNoEmptyCode = ListofTIDhasNoEmptyCode ...
+ " TID%<Tid>PID% "
%<LibSetSystemField(system, FieldName, value[bufIdx])>
%endif
%assign bufIdx = bufIdx + 1
%endforeach
%endforeach
%else
%foreach Tid = NumRuntimeExportedRates
%if !WHITE_SPACE(value[Tid])
%assign FieldName = "Cached" + fieldname1 + "%<Tid>" + fieldname2
%assign ListofTIDhasNoEmptyCode = ListofTIDhasNoEmptyCode ...
+ " TID%<Tid> "
%<LibSetSystemField(system, FieldName, value[Tid])>
%endif
%endforeach
%endif
%elseif !WHITE_SPACE(value[0])
%assign FieldName = "Cached" + fieldname1 + fieldname2
%<LibSetSystemField(system, FieldName, value[0])>
%assign ListofTIDhasNoEmptyCode = ListofTIDhasNoEmptyCode ...
+ " TID0 "
%endif
%assign FieldName = "Cached" + fieldname1 + fieldname2
%if TYPE(LibGetSystemField(system, FieldName)) == "Number"
%if !WHITE_SPACE(ListofTIDhasNoEmptyCode)
%<LibSetSystemField(system, FieldName, "/* Subsystem subrate code is not empty */")>
%else
%<LibSetSystemField(system, FieldName, "")>
%endif
%endif
%else
%assign FieldName = "Cached" + fieldname1 + fieldname2
%<LibSetSystemField(system, FieldName, value)>
%endif
%endfunction
%function LibAddToSystemField(system, fieldname, value) void
%if ISFIELD(system.InstanceCache, fieldname)
%assign system.InstanceCache.%<fieldname> = ...
system.InstanceCache.%<fieldname> + value
%else
%assign args = ["LibAddToSystemField", %<fieldname>]
%<SLibReportErrorWithIdAndArgs("RTW:tlc:FieldNotFound", args)>
%endif
%endfunction
%function LibGetSystemField(system, fieldname) void
%if ISFIELD(system.InstanceCache, fieldname)
%assign value = GETFIELD(system.InstanceCache, fieldname)
%else
%assign args = ["LibGetSystemField", %<fieldname>]
%<SLibReportErrorWithIdAndArgs("RTW:tlc:FieldNotFound", args)>
%endif
%return value
%endfunction
%function LibIsSystemField(system, fieldname) void
%return ISFIELD(system.InstanceCache, fieldname)
%endfunction
%function LibSetSubSystemField(subsysblk, fieldname) void
%error "LibSetSubSystemField is not implemented yet"
%endfunction
%function LibGetSubSystemField(subsysblk, fieldname) void
%error "LibGetSubSystemField is not implemented yet"
%endfunction
%function SLibGenCachedSystemFcnCallWithArgs(system, fcnType, csIdx, argVec) Output
%if (!WHITE_SPACE(LibGetSystemField(system, "Cached" + fcnType + "Fcn")))
%if LibSystemIsInlined(system)
%assign buffer = SLibGetBody%<fcnType>FcnCache(system)
%<buffer>
%else
%assign fcnInfo = LibGetFcnInfo(system, fcnType, system.CurrentTID)
%assign sysIdx = system.SystemIdx
%<LibGenSubsystemFcnCall(argVec, fcnInfo, SystemIdx, sysIdx, csIdx)>
%endif
%endif
%endfunction
%function LibGenCachedSystemFcnCall(system, fcnType, instIndex) Output
%<SLibGenCachedSystemFcnCallWithArgs(system, fcnType, instIndex, [])>
%endfunction
%function SLibGetCombinedFcnType(system, fcnType) void
%if fcnType == "Output" && !ISFIELD(system, "OutputFcn") && ...
!(ISFIELD(system, "OutputCalledInUpdate") && ...
system.OutputCalledInUpdate == "yes")
%assign fcnType = "OutputUpdate"
%endif
%return fcnType
%endfunction
%function SLibGenSystemFcnCallWithArgs(system, fcnType, instIndex, argVec) Output
%if LibSystemIsInlined(system)
%assign buffer = SLibGetBody%<fcnType>FcnCache(system)
%<buffer>
%else
%assign fcnInfo = LibGetFcnInfo(system, fcnType, system.CurrentTID)
%assign sysIdx = system.SystemIdx
%assign csIdx = instIndex
%<LibGenSubsystemFcnCall(argVec, fcnInfo, SystemIdx, sysIdx, csIdx)>
%endif
%endfunction
%function LibGenSystemFcnCall(system, fcnType, instIndex) Output
%<SLibGenSystemFcnCallWithArgs(system, ...
SLibGetCombinedFcnType(system, fcnType), instIndex, [])>
%endfunction
%function LibGenSystemFcnCallIn(system, inFcnType, fcnType, instIndex) Output
%<LibGenSystemFcnCall(system, fcnType, instIndex)>
%endfunction
%function SLibIsMultiRateAndPeriodicRateGrouping(system) void
%return !LibIsSingleRateSystem(system) && ...
FcnSysModuleIsPeriodicRateGrouping(system, "Outputs")
%endfunction
%function SLibIsMultiRateAndRateGrouping(system) void
%return !LibIsSingleRateSystem(system) && ...
FcnSysModuleIsRateGrouping(system, "Outputs")
%endfunction
%function SLibSystemFcnIsRateGroupType(fcnType) void
%return (fcnType == "Output" || fcnType == "Outputs" || ...
fcnType == "Update" || fcnType == "RootUpdate" || ...
fcnType == "OutputUpdate" || fcnType == "UpdateContStates" || ...
SLibContFcnPartitionGrouping(fcnType))
%endfunction
%function SLibSystemFcnPeriodicRateGrouping(system, fcnType)
%return FcnSysModuleIsPeriodicRateGrouping(system, fcnType)
%endfunction
%function SLibSystemTidUsedByRateGroup(system, fcnType)
%assert(LibIsSingleRateSystem(system) || ISFIELD(system, "CurrentTID"))
%assign tmpTid = FcnGetCurrentAccessTid()
%if SLibSystemFcnIsRateGroupType(fcnType)
%if !LibSystemIsRoot(system) && ...
LibIsSingleRateSystem(system) && SIZE(system.CallSites,0) > 1
%assign tmpTid = FcnGetSubsystemCodeBufTID(system)
%endif
%if LibAsynchronousTriggeredTID(tmpTid) || ...
SLibIsMultiRateAndRateGrouping(system)
%assign tid01Eq = ISEQUAL(SolverType, "FixedStep") && ...
FixedStepOpts.TID01EQ
%if ISEQUAL(tmpTid, 1) && tid01Eq
%assign tmpTid = 0
%endif
%else
%assign tmpTid = ""
%endif
%else
%assign tmpTid = ""
%endif
%return tmpTid
%endfunction
%function SLibSingleTasking() void
%return ( ::CompiledModel.HasPartitions == "no" && ...
(::CompiledModel.SolverType != "FixedStep" || ...
::CompiledModel.FixedStepOpts.SolverMode != "MultiTasking" ))
%endfunction
%function SLibConcurrentTasks() void
%return ::CompiledModel.ConcurrentTasks != "no"
%endfunction
%function SLibGenerateNativeThreads() void
%return (SLibConcurrentTasks() || LibIsDeploymentDiagram()) && ...
!IsModelReferenceTarget() && ...
((GenerateSampleERTMain && ::CompiledModel.ConfigSet.SystemTargetFile == "ert.tlc") ...
|| ::CompiledModel.ConfigSet.SystemTargetFile == "grt.tlc")
%endfunction
%function SLibIsPeriodicRateGrouping() void
%return ::CompiledModel.MdlGenPeriodicRateGroupingCode == "yes"
%endfunction
%assign rootSystem = ::CompiledModel.System[::CompiledModel.NumSystems - 1]
%with ::CompiledModel
%foreach sysIdx = NumSystems
%addtorecord System[sysIdx] InstanceCache {}
%endforeach
%endwith
%function LibIsSystemCached(system)
%return LibGetSystemField(system, "SystemCached")
%endfunction
%function LibIsSystemDumped(system)
%return LibGetSystemField(system, "SystemDumped")
%endfunction
%function LibIsSystemNonEmpty(system)
%return LibGetSystemField(system, "SystemNonEmpty")
%endfunction
%function LibIsSystemTerminateNonEmpty(system)
%return LibGetSystemField(system, "SystemTerminateNonEmpty")
%endfunction
%function LibIsSystemTerminateCached(system)
%return LibGetSystemField(system, "SystemTerminateCached")
%endfunction
%function LibGetSubsystemBlkTIDForTask(ssBlock, returnFundmentalTID) void
%assign subsystemTID = ssBlock.TaskToFirstTID
%if (SIZE(subsystemTID, 1) == 1) || ...
(TYPE(subsystemTID) == "Vector" && returnFundmentalTID)
%return subsystemTID[0]
%else
%return subsystemTID
%endif
%endfunction
%function LibGetSubsystemBlkTID(ssBlock, returnFundmentalTID) void
%assign subsystemTID = ssBlock.SubsystemTID
%if ISFIELD(ssBlock, "TriggerTID")
%assign tmpTid = ssBlock.TriggerTID[0]
%elseif ISEQUAL(subsystemTID, "constant")
%assign tmpTid = 0
%elseif TYPE(subsystemTID) == "Vector" && returnFundmentalTID
%if ISFIELD(ssBlock,"AsyncShellTID")
%assign tmpTid = ssBlock.AsyncShellTID
%else
%if (ssBlock.firstEntryOfTsMapIsGCD == "yes")
%assign tmpTid = subsystemTID[0]
%else
%assign tmpTid = "InvalidTid"
%endif
%endif
%else
%assign tmpTid = subsystemTID
%endif
%return tmpTid
%endfunction
%function FcnGetSysBlkTID(ssBlock, returnFundmentalTID) void
%return LibGetSubsystemBlkTIDForTask(ssBlock, returnFundmentalTID)
%endfunction
%function LibGetSubsystemTID(system, returnFundamentalTID) void
%assign tid = -1
%if system.Type == "root"
%assign tid = 0
%foreach tidIdx = NumSampleTimes
%if ::CompiledModel.SampleTime[tidIdx].PeriodAndOffset[0] > 0 && ...
!SLibModelWideEventTID(tidIdx)
%assign tid = tidIdx
%break
%endif
%endforeach
%return tid
%endif
%assign callSites = system.CallSites
%assign numCs = SIZE(callSites,0)
%assert (numCs > 0)
%foreach idx = numCs
%assign graphParentSys = ::CompiledModel.System[callSites[idx][2]]
%assign ssBlock = graphParentSys.Block[callSites[idx][3]]
%assign tmpTid = LibGetSubsystemBlkTIDForTask(ssBlock, returnFundamentalTID)
%if ISEQUAL(tid, -1)
%assign tid = tmpTid
%elseif !ISEQUAL(tid, tmpTid)
%assign tid = -1
%break
%endif
%endforeach
%return tid
%endfunction
%function FcnGetSubsystemTID(system, returnFundamentalTID) void
%return LibGetSubsystemTID(system, returnFundamentalTID)
%endfunction
%function FcnGetSubsystemCodeBufTID(system) void
%if system.Type == "root"
%assign tmpTid = LibGetSubsystemTID(system, TLC_TRUE)
%else
%assign callSites = system.CallSites
%assign numCs = SIZE(callSites,0)
%assert (numCs > 0)
%assign graphParentSys = ::CompiledModel.System[callSites[0][2]]
%assign ssBlock = graphParentSys.Block[callSites[0][3]]
%assign tmpTid = LibGetSubsystemBlkTIDForTask(ssBlock,TLC_TRUE)
%endif
%if LibAsynchronousTriggeredTID(tmpTid)
%assign tid = tmpTid
%else
%assign tmpTid = SLibIsMultiRateAndPeriodicRateGrouping(system) ? tmpTid:0
%assign tid01Eq = ISEQUAL(SolverType, "FixedStep") && FixedStepOpts.TID01EQ
%if tid01Eq && ISEQUAL(tmpTid,1)
%assign tid = 0
%else
%assign tid = tmpTid
%endif
%endif
%return tid
%endfunction
%function FcnGetSubsystemTaskToFirstTID(system) void
%if system.Type == "root"
%return FcnModelTaskToFirstTID(TLC_TRUE)
%else
%assign callSites = system.CallSites
%assign numCs = SIZE(callSites,0)
%assert (numCs > 0)
%assign graphParentSys = ::CompiledModel.System[callSites[0][2]]
%assign ssBlock = graphParentSys.Block[callSites[0][3]]
%return ssBlock.TaskToFirstTID
%endif
%endfunction
%function FcnGetSubsystemCustomCodeBufTID(system) void
%assert system.Type != "root"
%assign callSites = system.CallSites
%assign numCs = SIZE(callSites,0)
%assert (numCs > 0)
%assign graphParentSys = ::CompiledModel.System[callSites[0][2]]
%assign ssBlock = graphParentSys.Block[callSites[0][3]]
%if ISFIELD(ssBlock,"CustomCodeTID")
%assign tmpTid = ssBlock.CustomCodeTID
%else
%assign tmpTid = ""
%endif
%assert TYPE(tmpTid) != "Vector"
%if LibAsynchronousTriggeredTID(tmpTid)
%assign tid = tmpTid
%else
%assign tmpTid = SLibIsMultiRateAndPeriodicRateGrouping(system) ? tmpTid:0
%assign tid01Eq = ISEQUAL(SolverType, "FixedStep") && FixedStepOpts.TID01EQ
%if tid01Eq && ISEQUAL(tmpTid,1)
%assign tid = 0
%else
%assign tid = tmpTid
%endif
%endif
%return tid
%endfunction
%function FcnSubsystemIsAsycnTopSS(ss)
%return ISFIELD(ss, "IsTopAsyncSS")
%endfunction
%function FcnBlkIsAsyncTopSfcn(block)
%return block.AsyncSfcn
%endfunction
%function FcnAsyncTaskUpdatesTimersFromBaseRateSingleCore(tid)
%openfile tmpBuf
%assert SampleTime[tid].Asynchronous == "yes"
%assert SampleTime[tid].TimeSource == "BaseRate"
%switch SLibComparePriority(tid,0)
%case -1
%if SampleTime[tid].NeedAbsoluteTime == "yes"
/* Asynchronous task (with no priority assigned)
* reads absolute time */
switch(%<SLibGetDbBufWriteBuf(tid)>) {
case 0: %<SLibGetDbBufReadBuf(tid)> =1; break;
case 1: %<SLibGetDbBufReadBuf(tid)> =0; break;
default: %<SLibGetDbBufReadBuf(tid)> = ...
%<SLibGetDbBufLastBufWr(tid)>; break;
}
%if SampleTime[tid].ClockTickDataTypeId == tSS_DOUBLE
%<LibGetClockTick(tid)> = ...
%<SLibGetDbBufContTForTID(tid)>[%<SLibGetDbBufReadBuf(tid)>];
%else
%<LibGetClockTick(tid)> = ...
%<SLibGetDbBufClockTickForTID(tid)>[%<SLibGetDbBufReadBuf(tid)>];
%if SLibClockTickIsUnit32Pair(tid)
%<LibGetClockTickHigh(tid)> = ...
%<SLibGetDbBufClockTickHForTID(tid)>[%<SLibGetDbBufReadBuf(tid)>];
%endif
%endif
%<SLibGetDbBufReadBuf(tid)> = 0xFF;
%endif
%break
%case 0
/* Asynchronous task reads absolute time. Data (absolute time)
transfers between tasks with the same priority task doesn't
need protection
*/
%if SampleTime[tid].ClockTickDataTypeId == tSS_DOUBLE
%assert LibIsContinuous(0)
%<LibGetClockTick(tid)> = %<LibGetT()>;
%else
%<LibGetClockTick">LibGetClockTick(tid)> = %<LibGetClockTick">LibGetClockTick(0)>;
%if SLibClockTickIsUnit32Pair(tid)
%<LibGetClockTickHigh">LibGetClockTickHigh(tid)> = %<LibGetClockTickHigh">LibGetClockTickHigh(0)>;
%endif
%endif
%break
%case 1
/* Asynchronous task reads absolute time. Data (absolute time)
transfers from low priority task (base rate) to high priority
task (asynchronous rate). Double buffers are used to ensure
data integrity.
-- rtmL2HLastBufWr is the buffer index that is written last.
*/
%if SampleTime[tid].ClockTickDataTypeId == tSS_DOUBLE
%assert LibIsContinuous(0)
%<LibGetClockTick(tid)> = %<SLibGetL2HDbBufContT()>[%<SLibGetL2HLastBufWr()>];
%else
%<LibGetClockTick(tid)> = %<SLibGetL2HDbBufClockTick()>[%<SLibGetL2HLastBufWr()>];
%if SLibClockTickIsUnit32Pair(tid)
%<LibGetClockTickHigh(tid)> = %<SLibGetL2HDbBufClockTickH()>[%<SLibGetL2HLastBufWr()>];
%endif
%endif
%break
%case 2
/* Asynchronous task reads absolute time. Data (absolute time)
transfers from high priority task (base rate) to low priority
task (asynchronous rate). Double buffers are used to ensure
data integrity.
-- rtmH2LBufBeingRead is the index of the buffer being read
-- rtmH2LLastBufWr is the index of the buffer that is written last.
*/
if (%<SLibGetH2LLastBufWr(tid)> == 0) {
%<SLibGetH2LBufBeingRead(tid)> = 0;
%if SampleTime[tid].ClockTickDataTypeId == tSS_DOUBLE
%assert LibIsContinuous(0)
%<LibGetClockTick(tid)> = %<SLibGetH2LDbBufContTForTID(tid)>[0];
%else
%<LibGetClockTick(tid)> = %<SLibGetH2LDbBufClockTickForTID(tid)>[0];
%if SLibClockTickIsUnit32Pair(tid)
%<LibGetClockTickHigh(tid)> = %<SLibGetH2LDbBufClockTickHForTID(tid)>[0];
%endif
%endif
} else {
%<SLibGetH2LBufBeingRead(tid)> = 1;
%if SampleTime[tid].ClockTickDataTypeId == tSS_DOUBLE
%assert LibIsContinuous(0)
%<LibGetClockTick(tid)> = %<SLibGetH2LDbBufContTForTID(tid)>[1];
%else
%<LibGetClockTick(tid)> = %<SLibGetH2LDbBufClockTickForTID(tid)>[1];
%if SLibClockTickIsUnit32Pair(tid)
%<LibGetClockTickHigh(tid)> = %<SLibGetH2LDbBufClockTickHForTID(tid)>[1];
%endif
%endif
}
%break
%default
%<SLibReportErrorWithId("RTW:tlc:UnknownPriorityComp")>
%break
%endswitch
%closefile tmpBuf
%return tmpBuf
%endfunction
%function FcnAsyncTaskUpdatesTimersFromBaseRate(tid)
%if !SLibIsERTCodeFormat() || IsModelReferenceTarget()
%return ""
%endif
%openfile tmpBuf
%assert SampleTime[tid].Asynchronous == "yes"
%assert SampleTime[tid].TimeSource == "BaseRate"
%if RTMAbsTimeNeedTransProtection(tid)
%if SLibConcurrentTasks()
%<SLibCGIRMutexOp(1,SLibGetTimerSemID(tid))>
%<LibGetClockTick(tid)> = %LibGetClockTickBufForTID(tid)>;
%if SLibClockTickIsUnit32Pair(tid)
%<LibGetClockTickHigh(tid)> = %<SLibGetClockTickHBufForTID(tid)>;
%endif
%<SLibCGIRMutexOp(2,SLibGetTimerSemID(tid))>
%else
%<FcnAsyncTaskUpdatesTimersFromBaseRateSingleCore(tid)>
%endif
%else
%<LibGetClockTick">LibGetClockTick(tid)> = %<LibGetClockTick">LibGetClockTick(0)>;
%endif
%if SampleTime[tid].NeedFloatTime == "yes"
%<SLibUpdateFloatTimeForAsyncTask(tid)>
%endif
%closefile tmpBuf
%return tmpBuf
%endfunction
%function SLibIsCondExec(ss) void
%return ss.IsCondExec
%endfunction
%function SLibGetReusableLibrarySubsystemDir(system)
%if !ISFIELD(::CompiledModel, "RTWInfoMatFile")
%<LoadRTWInfoMatFileforTLC()>
%endif
%return "%<::CompiledModel.RTWInfoMatFile.sharedSourcesDir>"
%endfunction
%function SLibGetReusableLibraryOutputDirectory(system)
%assign BuildDir = SLibGetReusableLibrarySubsystemDir(system)
%if !FEVAL("exist", BuildDir, "dir")
%assign success = FEVAL( "mkdir", BuildDir )
%if success != 1
%<SLibReportErrorWithId("RTW:tlc:CannotCreateLibBuildDir")>
%endif
%endif
%return BuildDir
%endfunction
%endif