%%
%%
%%
%%Copyright2018-2019TheMathWorks,Inc.
%%
%%Abstract:
%%ThisTLClibraryfilecontainsthegeneralpurposeutilityfunctionsforserviceports.
%%
 
%if EXISTS("_SERVICELIB_") == 0
%assign _SERVICELIB_ = 1
 
%include "utillib.tlc"
 
%function SLibServicePortsExist() void
 %if !EXISTS(NumServicePorts) || NumServicePorts == 0
   %return TLC_FALSE
 %endif
 %return TLC_TRUE
%endfunction
 
%function SLibDeclareServicePortGlobalVarForCPPClassHelper(aSvc, argName, argTypeName) void
  %if !EXISTS(CPPClassTypeNames)
    %assign ::CPPClassTypeNames = []
  %endif
   
  %assign classTypeName = CPPClassName + argTypeName
  %assign classAlreadyEmitted = TLC_FALSE
  %assign numClassTypeNames = SIZE(::CPPClassTypeNames)[1]
  %foreach clsIdx = numClassTypeNames
    %if ::CPPClassTypeNames[clsIdx] == classTypeName
      %assign classAlreadyEmitted = TLC_TRUE
      %break
    %endif
  %endforeach
   
  %assign tmpBuf = ""
  %if classAlreadyEmitted
    %assign tmpBuf = tmpBuf + ...
      "static %<classTypeName> %<argName>; "
  %else
    %assign typeIdx = LibCGTypeToSLType(aSvc.ArginCGTypeIdx[0])
    %if (aSvc.ArginIsComplex[0])
      %assign typeName = LibGetDataTypeComplexNameFromId(typeIdx)
    %else
      %assign typeName = LibGetDataTypeNameFromId(typeIdx)
    %endif
    %assign ::CPPClassTypeNames = ::CPPClassTypeNames + classTypeName
    %if aSvc.Name == "SendData"
      %if aSvc.NumInArgs == 2
        %assign fcnArgs = "const %<typeName>* data, int32_T length, int32_T* status"
      %else
        %assign fcnArgs = "const %<typeName>* data, int32_T* status"
      %endif
      %assign fcnBody = "/* Add send data logic here */"
    %elseif aSvc.Name == "RecvData"
      %if aSvc.NumInArgs == 2
        %assign fcnArgs = "%<typeName>* data, int32_T length, int32_T* status"
      %else
        %assign fcnArgs = "%<typeName>* data, int32_T* status"
      %endif
      %assign fcnBody = "/* Add receive data logic here */"
    %else
      %return ""
    %endif
    %assign tmpBuf = tmpBuf + ...
      "class %<CPPClassName>%<argTypeName> : public %<argTypeName>" + ...
      "{ " + ...
      "public: " + ...
      "void %<aSvc.Name>(%<fcnArgs>) { /n" + ...
      "%<fcnBody> " + ...
      "}" + ...
      "};" + ...
      "static %<classTypeName> %<argName>; "
  %endif
  %return tmpBuf
%endfunction
 
%function SLibDeclareServicePortGlobalVarForCPPClass(constrFcn, argIdx) void
  %if !MessageServiceRootIO == 1 || !SLibServicePortsExist()
    %return
  %endif
  %assign tmpBuf = ""
  %assign argName = constrFcn.ArgNames[argIdx]
  %assign argType = constrFcn.ArgTypes[argIdx]
  %if argType < 0
    %return tmpBuf
  %endif
  %assign argTypeName = SLibGetTypeNameFromCGType(argType)
  %assign argTypeName = FEVAL("regexprep", argTypeName, "&", "", "once")
  %assign argTypeName = FEVAL("regexprep", argTypeName, " ", "")
  %with ServicePortInfoMap
    %foreach portIdx = NumServicePorts
      %assign thisPort = ServicePort[portIdx]
      %assign aSID = thisPort.SID
      %assign providingServices = thisPort.ProvidingServices
      %if !ISEMPTY(providingServices)
        %assign numProvidingSvc = SIZE(providingServices.ProvidingService)[1]
        %foreach i=numProvidingSvc
          %assign aProvidingService = providingServices.ProvidingService[i]
          %if aProvidingService.ModelConstructorArgIdx == argIdx
            %return SLibDeclareServicePortGlobalVarForCPPClassHelper(aProvidingService, argName, argTypeName)
          %endif
        %endforeach %% numProvidingSvc
      %endif %% !ISEMPTY(aProvidingService)
       
      %assign requestingServices = thisPort.RequestingServices
      %if !ISEMPTY(requestingServices)
        %assign numRequestingSvc = SIZE(requestingServices.RequestingService)[1]
        %foreach i=numRequestingSvc
          %assign aRequestingService = requestingServices.RequestingService[i]
          %if aRequestingService.ModelConstructorArgIdx == argIdx
            %return SLibDeclareServicePortGlobalVarForCPPClassHelper(aRequestingService, argName, argTypeName)
          %endif
        %endforeach %% numRequestingSvc
      %endif %% !ISEMPTY(aRequestingService)
    %endforeach %% NumServicePorts
  %endwith %%ServicePortInfoMap
  %return tmpBuf
%endfunction
 
%function SLibEmitMessageQueueFunctions() Output
  %% Currently C code gen is not supported. This function is being
  %% kept for when C is supported
  %if SLibRTWCPPClassActive()
    %return
  %endif
   
  %if !MessageServiceRootIO == 1 || !SLibServicePortsExist()
    %return
  %endif
  %with ServicePortInfoMap
    %foreach portIdx = NumServicePorts
      %assign thisPort = ServicePort[portIdx]
      %assign aSID = thisPort.SID
      %assign providingServices = thisPort.ProvidingServices
      %if !ISEMPTY(providingServices) && thisPort.IsTopMdlRootSP
        %assign numProvidingSvc = SIZE(providingServices.ProvidingService)[1]
        %foreach i=numProvidingSvc
          %assign aProvidingService = providingServices.ProvidingService[i]
          %if aProvidingService.DworkIdx >= 0
            %if aProvidingService.Name == "RecvData"
              %<SLibEmitReadMessage(aProvidingService)>
            %elseif aProvidingService.Name == "SendData"
              %<SLibEmitSendMessage(aProvidingService)>
            %endif
          %endif
        %endforeach
      %endif
    %endforeach
  %endwith
%endfunction
 
%function SLibEmitReadMessage(aService) Output
  %% Currently C code gen is not supported. This function is being
  %% kept for when C is supported
  %if SLibRecvDataForSampleMainNeeded()
    %assign typeIdx = LibCGTypeToSLType(aService.ArginCGTypeIdx[1])
    %assign typeName = LibCGTypeName(aService.ArginCGTypeIdx[1])
    %assign cTypeName = ::CompiledModel.DataTypes.DataType[typeIdx].DataTypeName
    void receiveData_%<cTypeName>(void* host, %<typeName>* data, int32_T* status)
    {
      /* Add receive data logic here */
    }
  %endif
%endfunction
 
%function SLibEmitSendMessage(aService) Output
  %% Currently C code gen is not supported. This function is being
  %% kept for when C is supported
  %if SLibSendDataForSampleMainNeeded()
    %assign typeIdx = LibCGTypeToSLType(aService.ArginCGTypeIdx[1])
    %assign typeName = LibCGTypeName(aService.ArginCGTypeIdx[1])
    %assign cTypeName = ::CompiledModel.DataTypes.DataType[typeIdx].DataTypeName
    void sendData_%<cTypeName>(void* host, const %<typeName>* data, int32_T* status)
    {
      /* Add send data logic here */
    }
  %endif
%endfunction
 
%function SLibRecvDataForSampleMainNeeded() void
  %if MessageServiceRootIO == 1 && ...
    SLibModelHasServicePortDWork() && ...
    !IsModelReferenceTarget() && ...
    !SLibRTWCPPClassActive()
    %with ServicePortInfoMap
      %foreach portIdx = NumServicePorts
        %assign thisPort = ServicePort[portIdx]
        %assign aSID = thisPort.SID
        %assign providingServices = thisPort.ProvidingServices
        %if !ISEMPTY(providingServices)
          %assign numProvidingSvc = SIZE(providingServices.ProvidingService)[1]
          %foreach i=numProvidingSvc
            %assign aProvidingService = providingServices.ProvidingService[i]
            %if aProvidingService.DworkIdx >= 0 && aProvidingService.Name == "RecvData"
              %return TLC_TRUE
            %endif
          %endforeach %% numProvidingSvc
        %endif %% !ISEMPTY(aProvidingService)
      %endforeach %% NumServicePorts
    %endwith %%ServicePortInfoMap
  %endif
  %return TLC_FALSE
%endfunction
 
%function SLibSendDataForSampleMainNeeded() void
  %if MessageServiceRootIO == 1 && ...
    SLibModelHasServicePortDWork() && ...
    !IsModelReferenceTarget() && ...
    !SLibRTWCPPClassActive()
    %with ServicePortInfoMap
      %foreach portIdx = NumServicePorts
        %assign thisPort = ServicePort[portIdx]
        %assign aSID = thisPort.SID
        %assign providingServices = thisPort.ProvidingServices
        %if !ISEMPTY(providingServices)
          %assign numProvidingSvc = SIZE(providingServices.ProvidingService)[1]
          %foreach i=numProvidingSvc
            %assign aProvidingService = providingServices.ProvidingService[i]
            %if aProvidingService.DworkIdx >= 0 && aProvidingService.Name == "SendData"
              %return TLC_TRUE
            %endif
          %endforeach %% numProvidingSvc
        %endif %% !ISEMPTY(aProvidingService)
      %endforeach %% NumServicePorts
    %endwith %%ServicePortInfoMap
  %endif
  %return TLC_FALSE
%endfunction
 
%function SLibEmitRootPortServiceInitForSampleMain() Output
  %if !MessageServiceRootIO == 1 || !SLibServicePortsExist()
    %return
  %endif
  %% Currently C code gen is not supported. This function is being
  %% kept for when C is supported
  %if SLibRTWCPPClassActive()
    %return
  %endif
   
  %if SLibModelHasServicePortDWork() && !IsModelReferenceTarget()
    %with ServicePortInfoMap
      %openfile serviceBuf
      %foreach portIdx = NumServicePorts
        %assign thisPort = ServicePort[portIdx]
 
        %assign providingServices = thisPort.ProvidingServices
        %if !ISEMPTY(providingServices)
          %assign numProvidingSvc = SIZE(providingServices.ProvidingService)[1]
          %foreach i=numProvidingSvc
            %assign aProvidingService = providingServices.ProvidingService[i]
            %if aProvidingService.DworkIdx >= 0
              %assign typeIdx = LibCGTypeToSLType(aProvidingService.ArginCGTypeIdx[1])
              %assign cTypeName = ::CompiledModel.DataTypes.DataType[typeIdx].DataTypeName
              %assign dwRec = ::CompiledModel.DWorks.DWork[aProvidingService.DworkIdx]
              %assign providerBlk = System[dwRec.SigSrc[0]].Block[dwRec.SigSrc[2]]
              %if (TYPE(providerBlk.Type) == "Identifier" && ...
                (providerBlk.Type == "Inport" || providerBlk.Type == "Outport" || providerBlk.Type == "Opaque"))
                %assign dworkvar = providerBlk.Identifier + "_" + dwRec.Name
                %assign serviceFcnPtr = LibGetDWorkStruct() + "." + dworkvar + "." + aProvidingService.Name
                %if aProvidingService.Name == "RecvData"
                  %assign serviceFcnPtrRHS = "receiveData_%<cTypeName>"
                %elseif aProvidingService.Name == "SendData"
                  %assign serviceFcnPtrRHS = "sendData_%<cTypeName>"
                %endif
                %assign nulldef = SLibGetNullDefinitionFromTfl()
                %assign hostPtr = LibGetDWorkStruct() + "." + dworkvar + ".host"
                %assign ppIf = SLibIfVariantConditionForm(dwRec.VariantCondition)
                %assign ppEndif = SLibEndIfVariantConditionForm(dwRec.VariantCondition)
                %<ppIf>
                %<serviceFcnPtr> = %<serviceFcnPtrRHS>;
                %<hostPtr> = %<nulldef>;
                %<ppEndif>
              %endif
            %endif
          %endforeach %% numProvidingSvc
        %endif %% !ISEMPTY(aProvidingService)
      %endforeach %% NumServicePorts
      %closefile serviceBuf
    %endwith %%ServicePortInfoMap
    %if !ISEMPTY(serviceBuf)
      /* Initialize message service DWork */
      %<serviceBuf>
    %endif
  %endif
%endfunction
 
%function SLibModelHasServicePortDWork() void
  %if SLibServicePortsExist()
    %with ServicePortInfoMap
      %foreach portIdx = NumServicePorts
        %assign thisPort = ServicePort[portIdx]
        %assign providingServices = thisPort.ProvidingServices
        %if !ISEMPTY(providingServices)
          %assign numProvidingSvc = SIZE(providingServices.ProvidingService)[1]
          %foreach i=numProvidingSvc
            %assign aProvidingService = providingServices.ProvidingService[i]
            %if aProvidingService.DworkIdx >= 0
              %return TLC_TRUE
            %endif
          %endforeach
        %endif
        %assign requestingServices = thisPort.RequestingServices
        %if !ISEMPTY(requestingServices)
          %assign numRequestingSvc = SIZE(requestingServices.RequestingService)[1]
          %foreach i=numRequestingSvc
            %assign aRequestingService = requestingServices.RequestingService[i]
            %if aRequestingService.DworkIdx >= 0
              %return TLC_TRUE
            %endif
          %endforeach
        %endif
      %endforeach
    %endwith
  %endif
  %return TLC_FALSE
%endfunction
 
%function SLibGetModelBlockStructDWorkArgIfExists(aBlock, fcnType) void
  %assign modelBlkDWork = ""
  %assign blkInterface = GetModelrefInterface(aBlock)
  %if SLibGetStructDWorkIdxForModelRefBlk(aBlock) >= 0 || ...
    blkInterface.rtmAllocateInParent %% Even though the API says RTM but this should work for model self in general
    %assign modelBlkDWork = SLibGetModelBlockStructDWorkArg([],GetBaseSystemIdx(),aBlock,fcnType,0)
  %endif
  %return modelBlkDWork
%endfunction
 
%function SLibGetCompleteServiceDWorkPath(varGroupElemId, isCoderData) void
  %if isCoderData
    %assign selfAccess = ""
  %else
    %assign selfAccess = "dwork."
  %endif
  %if ::CompiledModel.ModelRefSimpInterface
    %assign dworkPath = selfAccess + varGroupElemId
  %elseif SLibSimTargetUsesModelSelf()
    %assign dworkPath = "rtm.dwork." + varGroupElemId
  %elseif ModelrefBlockNeedsDwork()
    %if isCoderData
      %assign dworkPath = "rtm." + varGroupElemId
    %else
      %assign dworkPath = "rtdw." + varGroupElemId
    %endif
  %else
    %assign dworkPath = FcnSysVarGroupNonreusedName(System[NumSystems-2],"DWork") + "." + varGroupElemId
  %endif
  %return dworkPath
%endfunction
 
%function SLibGetServiceDWorkPathFromModelSelfIfNecessary(varGroupElemId, isCoderData) void
  %if isCoderData
    %assign selfAccess = ""
  %else
    %assign selfAccess = "dwork."
  %endif
  %if OkToMultiInstanceModelref && SLibGetSelfCoderDataGroupVarGroupIndex() > -1
    %% This is to deal with the SimTarget case for model self:
    %% Within the model, dwork is accessed through MdlrefDW's rtm field. But MdlrefDW is not
    %% added to a parent model.
    %assign dworkPathFromModelSelf = selfAccess + varGroupElemId
  %else
    %assign dworkPathFromModelSelf = ""
  %endif
  %return dworkPathFromModelSelf
%endfunction
 
%function SLibGetChildModelServiceDWorkPath(childSvc)
  %if !ISEMPTY(childSvc.DWorkPathFromModelSelf)
    %return childSvc.DWorkPathFromModelSelf
  %else
    %return childSvc.DWorkPath
  %endif
%endfunction
 
%function SLibCallServiceFunctionCpp(sid, serviceName, portIdx, portType, dworkIdx, payload, length, outVar) Output
  %% This function is valid only for non-CPP encap codegen
  %assert SLibRTWCPPClassActive()
  %assign sysIdx = GetBaseSystemIdx()
  %assign blkIdx = SLibGetBlockIdxFromSID(System[sysIdx], sid)
  %assert blkIdx > -1
  %assign aBlock = System[sysIdx].Block[blkIdx]
  %if aBlock.Type == "ModelReference"
    %assign pairedService = SLibGetPairedServiceHelper(portIdx, serviceName, TLC_FALSE, portType, aBlock)
    %assert !ISEMPTY(pairedService)
    %assign modelBlkVarName = SLibGetCPPMdlRefObjName(sysIdx, blkIdx)
    %if !ISEMPTY(modelBlkVarName)
      %assign serviceDWorkPath = modelBlkVarName + "." + pairedService.AccessorFcnName + "()"
      %assign serviceFcn = serviceDWorkPath + "." + serviceName
    %else
      %assign serviceDWorkPath = dworkPath
      %assign serviceFcn = serviceDWorkPath + "." + serviceName
    %endif
  %endif
  %if !ISEMPTY(payload)
    %if !ISEMPTY(outVar)
      %if !ISEMPTY(length)
        %<serviceFcn>(%<payload>, %<length>, %<outVar>);
      %else
        %<serviceFcn>(%<payload>, %<outVar>);
      %endif
    %else
      %if !ISEMPTY(length)
        %<serviceFcn>(%<payload>, %<length>);
      %else
        %<serviceFcn>(%<payload>);
      %endif
    %endif
  %else
      %if !ISEMPTY(outVar)
        %<serviceFcn>(%<outVar>);
      %else
        %<serviceFcn>();
      %endif
  %endif
%endfunction
 
%function SLibCallServiceFunction(sid, serviceName, portIdx, portType, dworkIdx, payload, length, outVar) Output
  %assign aPortType = "SVC_INVALID_PORT"
  %if portType == 0
    %assign aPortType = "SVC_IN_PORT"
  %elseif portType == 1
    %assign aPortType = "SVC_OUT_PORT"
  %endif
  %% This function is valid only for non-CPP encap codegen
  %if SLibRTWCPPClassActive()
    %<SLibCallServiceFunctionCpp(sid, serviceName, portIdx, aPortType, dworkIdx, payload, length, outVar)>
    %return
  %endif
   
  %assign sysIdx = GetBaseSystemIdx()
  %assign blkIdx = SLibGetBlockIdxFromSID(System[sysIdx], sid)
  %assert blkIdx > -1
  %assign aBlock = System[sysIdx].Block[blkIdx]
  %if aBlock.Type == "ModelReference"
    %assign pairedService = SLibGetPairedServiceHelper(portIdx, serviceName, TLC_FALSE, aPortType, aBlock)
    %assert !ISEMPTY(pairedService)
    %assign dworkPath = SLibGetChildModelServiceDWorkPath(pairedService)
    %assert !ISEMPTY(dworkPath)
    %assign modelBlkDWork = SLibGetModelBlockStructDWorkArgIfExists(aBlock,::BlockFcn)
    %if !ISEMPTY(modelBlkDWork)
      %assign serviceDWorkPath = modelBlkDWork + "." + dworkPath
      %assign serviceFcn = serviceDWorkPath + "." + serviceName
      %assign host = serviceDWorkPath + ".host"
    %else
      %assign serviceDWorkPath = dworkPath
      %assign serviceFcn = serviceDWorkPath + "." + serviceName
      %assign host = serviceDWorkPath + ".host"
    %endif
  %else
    %assign dwRec = System[sysIdx].Block[blkIdx].DWork[dworkIdx]
    %assign dworkvar = System[sysIdx].Block[blkIdx].Identifier + "_" + dwRec.Name
    %assign serviceFcn = LibGetDWorkStruct() + "." + dworkvar + "." + serviceName
    %assign host = LibGetDWorkStruct() + "." + dworkvar + "." + "host"
  %endif
 
  %assign nulldef = SLibGetNullDefinitionFromTfl()
  if (%<serviceFcn> != %<nulldef>)
  {
  %if !ISEMPTY(payload)
    %if !ISEMPTY(outVar)
      %if !ISEMPTY(length)
        %<serviceFcn>(%<host>, %<payload>, %<length>, %<outVar>);
      %else
        %<serviceFcn>(%<host>, %<payload>, %<outVar>);
      %endif
    %else
      %if !ISEMPTY(length)
        %<serviceFcn>(%<host>, %<payload>, %<length>);
      %else
        %<serviceFcn>(%<host>, %<payload>);
      %endif
    %endif
  %else
      %if !ISEMPTY(outVar)
        %<serviceFcn>(%<host>, %<outVar>);
      %else
        %<serviceFcn>(%<host>);
      %endif
  %endif
  }
%endfunction
 
%function FcnCacheServiceFcnLocalVars(thisSystem, sysFcn, cTID, isRG) void
  %assign isCPPEncapMdlRef = GenerateClassInterface && ...
    IsModelReferenceBaseSys(thisSystem)
  %assign hostUnused = TLC_TRUE
  %with thisSystem.Interface
  %% Handle the casting of the "host" argument of a service function
  %if SysFcnArgNeeded(sysFcn, RTMArgDef, cTID, isRG)
    %openfile localRTMVar
    %if ::CompiledModel.RTWCGModules.RTWCGModule[thisSystem.CGIRModuleIdx].SimplifiedInterface
      %<::tSimStructType> *%<::tSimStruct> = (%<FcnGetSFcnDWorkType(thisSystem)>*) host;
    %else
      %<::tSimStructType> *%<::tSimStruct> = &((%<FcnGetSFcnDWorkType(thisSystem)>*)host)->rtm;
    %endif
    %closefile localRTMVar
    %<FcnCacheModelRefLocalVars(thisSystem, sysFcn, cTID, localRTMVar)>
    %assign hostUnused = TLC_FALSE
  %endif
  %if SysFcnArgNeeded(sysFcn, DWorkArgDef, cTID, isRG)
    %assign varGroupIdx = FcnSysVarGroupIndex(thisSystem, "DWork", 0)
    %assign varGroup = ::CompiledModel.VarGroups.VarGroup[varGroupIdx]
    %assign varGroupLocalName = varGroup.LocalName
    %assign varGroupType = FcnSysVarGroupType(thisSystem,"DWork")
    %openfile localDWorkVar
    %<varGroupType> *%<varGroupLocalName> = &((%<FcnGetSFcnDWorkType(thisSystem)>*)host)->rtdw;
    %closefile localDWorkVar
    %<FcnCacheModelRefLocalVars(thisSystem, sysFcn, cTID, localDWorkVar)>
    %assign hostUnused = TLC_FALSE
  %endif
  %if !isCPPEncapMdlRef && SysFcnArgNeeded(sysFcn, BlockIOArgDef, cTID, isRG)
    %assign varGroupIdx = FcnSysVarGroupIndex(thisSystem, "BlockIO", 0)
    %assign varGroup = ::CompiledModel.VarGroups.VarGroup[varGroupIdx]
    %assign varGroupLocalName = varGroup.LocalName
    %assign varGroupType = FcnSysVarGroupType(thisSystem,"BlockIO")
    %openfile localBlockIOVar
    %<varGroupType> *%<varGroupLocalName> = &((%<FcnGetSFcnDWorkType(thisSystem)>*)host)->rtb;
    %closefile localBlockIOVar
    %<FcnCacheModelRefLocalVars(thisSystem, sysFcn, cTID, localBlockIOVar)>
    %assign hostUnused = TLC_FALSE
  %endif
  %if hostUnused
    %openfile localUnused
    %<SLibUnusedParameter("host")>
    %closefile localUnused
    %<FcnCacheModelRefLocalVars(thisSystem, sysFcn, cTID, localUnused)>
  %endif
  %endwith
%endfunction
 
%function SLibGetPairedServiceAtMdlBoundary(aPort, aService, aBlk) void
  %assign isDelegation = aService.DelegatedPortIdx >= 0
  %assign portIdx = aPort.ServicePortIdx
  %if isDelegation
    %assign portIdx = aService.DelegatedPortIdx
  %endif
  %return SLibGetPairedServiceHelper(portIdx, aService.Name, isDelegation, aPort.ServicePortType, aBlk)
%endfunction
 
%function SLibPortTypesAreInOutPair(aPortType1, aPortType2) void
  %if aPortType1 == "SVC_IN_PORT" && aPortType2 == "SVC_OUT_PORT"
    %return TLC_TRUE
  %endif
  %if aPortType2 == "SVC_IN_PORT" && aPortType1 == "SVC_OUT_PORT"
    %return TLC_TRUE
  %endif
  %return TLC_FALSE
%endfunction
 
%function SLibGetPairedServicePort(aServicePortIdx, isDelegation, aPortType, aBlk) void
  %if aBlk.Type == "ModelReference"
    %assign interface = GetModelrefInterface(aBlk)
    %foreach portIdx = interface.NumServicePorts
      %assign thisPort = interface.ServicePort[portIdx]
      %assign portTypesAreInOutPair = SLibPortTypesAreInOutPair(thisPort.ServicePortType, aPortType)
      %assign portTypesAreTheSame = thisPort.ServicePortType == aPortType
      %assign portTypesOk = (!isDelegation && portTypesAreInOutPair) || (isDelegation && portTypesAreTheSame)
      %if portTypesOk && thisPort.ExternalPortIdx == aServicePortIdx
        %return thisPort
      %endif
    %endforeach
  %endif
  %return ""
%endfunction
 
%function SLibGetPairedServiceHelper(aServicePortIdx, aServiceName, isDelegation, aPortType, aBlk) void
  %if aBlk.Type == "ModelReference"
    %assign interface = GetModelrefInterface(aBlk)
    %foreach portIdx = interface.NumServicePorts
      %assign thisPort = interface.ServicePort[portIdx]
      %assign portTypesAreInOutPair = SLibPortTypesAreInOutPair(thisPort.ServicePortType, aPortType)
      %assign portTypesAreTheSame = thisPort.ServicePortType == aPortType
      %assign portTypesOk = (!isDelegation && portTypesAreInOutPair) || (isDelegation && portTypesAreTheSame)
      %if ISFIELD(thisPort, "RequestingService")
        %assign requestingServices = thisPort.RequestingService
        %assign numRequestingSvc = SIZE(requestingServices)[1]
        %if numRequestingSvc > 0 && ...
          thisPort.ExternalPortIdx == aServicePortIdx && ...
          portTypesOk
          %if numRequestingSvc == 1
            %if requestingServices.Name == aServiceName
              %return requestingServices
            %endif
          %else
            %foreach svcIdx=numRequestingSvc
              %assign thisService = requestingServices[svcIdx]
              %if thisService.Name == aServiceName
                %return thisService
              %endif
            %endforeach
          %endif
        %endif
      %endif
      %if ISFIELD(thisPort, "ProvidingService")
        %assign providingServices = thisPort.ProvidingService
        %assign numProvidingSvc = SIZE(providingServices)[1]
        %if numProvidingSvc > 0 && ...
          thisPort.ExternalPortIdx == aServicePortIdx && ...
          portTypesOk
          %if numProvidingSvc == 1
            %if providingServices.Name == aServiceName
              %return providingServices
            %endif
          %else
            %foreach svcIdx=numProvidingSvc
              %assign thisService = providingServices[svcIdx]
              %if thisService.Name == aServiceName
                %return thisService
              %endif
            %endforeach
          %endif
        %endif
      %endif
    %endforeach
  %endif
  %return ""
%endfunction
 
%function SLibGetPairedServiceAndPort(aPort, aService) void
  %% This returns a service port and service directly
  %% connected to a given service port and service
  %% ---/ /---
  %% | |
  %% |======>| Give p1 and a service in p1
  %% |p1 p2| Return p2 and the matching service in p2
  %% ---/ /---
  %%
  %createrecord aRecord { port ""; service ""}
  %if SLibServicePortsExist() && !ISEMPTY(aService.PairedBlockSID)
    %with ServicePortInfoMap
      %foreach portIdx = NumServicePorts
        %assign thisPort = ServicePort[portIdx]
        %if thisPort.ServicePortType == aPort.ServicePortType || ...
            thisPort.ServicePortIdx!= aService.PairedPortIdx
          %continue
        %endif
        %assign aSID = thisPort.SID
        %if aSID == aService.PairedBlockSID
          %assign providingServices = thisPort.ProvidingServices
          %if !ISEMPTY(providingServices)
            %assign numProvidingSvc = SIZE(providingServices.ProvidingService)[1]
            %foreach i=numProvidingSvc
              %assign aProvidingService = providingServices.ProvidingService[i]
              %if aProvidingService.Name == aService.Name
                %assign aRecord.port = thisPort
                %assign aRecord.service = aProvidingService
                %return aRecord
              %endif
            %endforeach
          %endif
          %assign requestingServices = thisPort.RequestingServices
          %if !ISEMPTY(requestingServices)
            %assign numRequestingSvc = SIZE(requestingServices.RequestingService)[1]
            %foreach i=numRequestingSvc
              %assign aRequestingService = requestingServices.RequestingService[i]
              %if aRequestingService.Name == aService.Name
                %assign aRecord.port = thisPort
                %assign aRecord.service = aRequestingService
                %return aRecord
              %endif
            %endforeach
          %endif
        %endif
      %endforeach
    %endwith
  %endif
  %return aRecord
%endfunction
 
%function SLibGetDelegatedServiceInfo(aPort, aService) void
  %% /------------- Given a service port p2,
  %% | and a service in that port
  %% p2| p1 this function return the delegation
  %%===>| o===> info stored in the child's service port p1
  %% | In1
  %% |
  %% /-------------
  %createrecord aRecord { path ""; host ""; serviceName ""; variantCondition ""}
  %if aService.DelegatedDworkIdx >= 0 || aService.DelegatedDworkIdx == -2
    %assign paired = SLibGetPairedServiceAndPort(aPort, aService)
    %if !ISEMPTY(paired.port)
      %assign aSID = aService.DelegatedSID
      %if aService.DelegatedDworkIdx == -2
        %assign aSID = paired.port.SID
      %endif
      %assign mdlBlk = SLibGetMdlBlockFromSID(aSID)
      %if !ISEMPTY(mdlBlk)
        %assign pairedServiceInChildMdl = SLibGetPairedServiceAtMdlBoundary(paired.port, paired.service, mdlBlk)
        %if !ISEMPTY(pairedServiceInChildMdl)
          %assign sysIdx = GetBaseSystemIdx()
          %with System[sysIdx]
            %assign dworkIdx = SLibGetStructDWorkIdxForModelRefBlk(mdlBlk)
            %if dworkIdx < 0
              %assign blkInterface = GetModelrefInterface(mdlBlk)
              %if blkInterface.rtmAllocateInParent
                %assign modelBlkDWork = SLibGetPathToModelBlockSelf(mdlBlk)
              %elseif ModelrefBlockNeedsDwork()
                %% return empty (assert?)
                %return aRecord
              %else
                %% single instance model block
                %assign modelBlkDWork = FcnSysVarGroupNonreusedName(System[NumSystems-2],"DWork")
              %endif
            %else
              %assign dwRec = ...
                ::CompiledModel.DWorks.DWork[mdlBlk.DWork[dworkIdx].FirstRootIdx]
              %assign modelBlkDWork = LibGetRecordIdentifier(dwRec)
            %endif
          %endwith
          %if !ISEMPTY(modelBlkDWork)
            %assign pairedDelegatedDworkPath = pairedServiceInChildMdl.DelegatedDworkPath
            %assign dwPrefix = SLibGetSelfCoderDataGroupVarGroupIndex() > -1 ? "" : "rtdw."
            %if !ISEMPTY(pairedDelegatedDworkPath)
              %assign aRecord.path = modelBlkDWork + "." + pairedDelegatedDworkPath
              %assign aRecord.host = dwPrefix + modelBlkDWork + "." + pairedServiceInChildMdl.DelegatedHost
              %assign aRecord.serviceName = pairedServiceInChildMdl.DelegatedServiceName
              %assign aRecord.variantCondition = pairedServiceInChildMdl.DWorkVariantCondition
            %else
              %assign dworkPath = SLibGetChildModelServiceDWorkPath(pairedServiceInChildMdl)
              %if !ISEMPTY(dworkPath)
                %assign aRecord.path = modelBlkDWork + "." + dworkPath
                %assign aRecord.host = dwPrefix + modelBlkDWork
                %assign aRecord.serviceName = pairedServiceInChildMdl.CGFcnName
                %assign aRecord.variantCondition = pairedServiceInChildMdl.DWorkVariantCondition
              %endif
            %endif
          %endif
        %endif
      %endif
    %endif
  %endif
  %return aRecord
%endfunction
 
%function SLibIsServiceFcn(system, aFcnType, aTID)
  %assign thisModule = ...
    ::CompiledModel.RTWCGModules.RTWCGModule[system.CGIRModuleIdx]
  %if (aFcnType == "OutputUpdate" || aFcnType == "Output" ) && ...
    TYPE(aTID) == "Number" && aTID > 0 && ...
    ISFIELD(SampleTime[aTID], "EntryFcnName") && ...
    ISFIELD(thisModule, "SystemFunctions") && ...
    ISFIELD(thisModule.SystemFunctions, SampleTime[aTID].EntryFcnName)
    %assign fcnIndex = GETFIELD(thisModule.SystemFunctions, SampleTime[aTID].EntryFcnName)
    %assign thisFcn = thisModule.Function[fcnIndex]
    %if thisFcn.IsServiceFcn == TLC_TRUE
      %return TLC_TRUE
    %endif
  %endif
  %return TLC_FALSE
%endfunction
 
%%determinewhetheragiventidisaservicetasktid;
%function SLibIsServiceTaskTID(aTID)
  %assign sampleTime = SampleTime[aTID]
  %if TYPE(aTID) == "Number" && aTID > 0 && ...
    ISFIELD(sampleTime, "EntryFcnName") && ...
    ISFIELD(sampleTime, "Asynchronous") && ...
    ISFIELD(sampleTime, "EventSourceType") && ...
    ISFIELD(sampleTime, "ExplicitTasking")
    %assign asynchronous = GETFIELD(sampleTime, "Asynchronous")
    %assign eventSource = GETFIELD(sampleTime, "EventSourceType")
    %assign explicitTask = GETFIELD(sampleTime, "ExplicitTasking")
    %if asynchronous == "yes" && eventSource == "SimEvent" && ...
        explicitTask == "yes"
      %return TLC_TRUE
    %endif
     
    %if eventSource == "AsyncSfcnBlk" && ...
        ISFIELD(sampleTime, "IsMessageTriggered")
      %if GETFIELD(sampleTime, "IsMessageTriggered") == 1
        %return TLC_TRUE
      %endif
    %endif
  %endif
  %return TLC_FALSE
%endfunction
 
%function SLibCacheAndRestoreServiceDWorkNeeded() void
  %return IsModelReferenceTarget() && ...
    (SLibZeroMemory">SLibZeroMemory("RTM") || SLibZeroMemory">SLibZeroMemory("DWork")) && ...
    (!SLibModelDWorkStructIsEmpty() || SLibIsSelfStructured())
%endfunction
 
%function SLibCacheServicePortDWork() Output
  %if !SLibServicePortsExist() || SLibRTWCPPClassActive()
    %return
  %endif
  %% Because a model's service port dwork may be set prior to the model's init
  %% function is called, we have to cache the service port DWork prior to
  %% the DWork being memset to zero. After the memset, the cached values
  %% will be restored (by SLibRestoreServicePortDWork). At this point.
  %% only the requester side of a model hierarchy needs to be cached.
  %% The provider side does a bit-wise copy of the child port after
  %% the child has been initialized (and after the memset is done).
  %with ServicePortInfoMap
  %assign argIdx = 0
  %foreach portIdx = NumServicePorts
    %assign thisPort = ServicePort[portIdx]
    %if thisPort.IsTopMdlRootSP == 1
      %continue
    %endif
    %assign providingServices = thisPort.ProvidingServices
    %if !ISEMPTY(providingServices)
      %assign numProvidingSvc = SIZE(providingServices.ProvidingService)[1]
      %foreach i=numProvidingSvc
        %assign aProvidingService = providingServices.ProvidingService[i]
        %if aProvidingService.DworkIdx >= 0
          %assign dwRec = ::CompiledModel.DWorks.DWork[aProvidingService.DworkIdx]
          %assign dwName = ...
            FcnCGIRCGVarHelper(dwRec.VarGroupIdx[0], dwRec.VarGroupIdx[1], ...
            TLC_FALSE, GetBaseSystemIdx(), SLibDWorkWidth(dwRec), "", -1, ...
            "", 0, TLC_FALSE)
          %assign cgTypeIdx = SLibGetRecordContainerCGTypeIdx(dwRec)
          %assign dwType = LibCGTypeName(cgTypeIdx)
          %assign argName = "service%<argIdx>"
          %assign ppIf = SLibIfVariantConditionForm(dwRec.VariantCondition)
          %assign ppEndif = SLibEndIfVariantConditionForm(dwRec.VariantCondition)
          %<ppIf>
          %<dwType> %<argName> = %<dwName>;
          %<ppEndif>
          %assign argIdx = argIdx + 1
        %endif
      %endforeach
    %endif
  %endforeach
  %endwith
%endfunction
 
%function SLibRestoreServicePortDWork() Output
  %if !SLibServicePortsExist() || SLibRTWCPPClassActive()
    %return
  %endif
  %% Because a model's service port dwork may be set prior to the model's init
  %% function is called, we have to cache the service port DWork prior to
  %% the DWork being memset to zero. After the memset, the cached vaules
  %% will be restored (by this function)
  %with ServicePortInfoMap
    %assign argIdx = 0
    %foreach portIdx = NumServicePorts
      %assign thisPort = ServicePort[portIdx]
      %if thisPort.IsTopMdlRootSP == 1
        %continue
      %endif
      %assign providingServices = thisPort.ProvidingServices
      %if !ISEMPTY(providingServices)
        %assign numProvidingSvc = SIZE(providingServices.ProvidingService)[1]
        %foreach i=numProvidingSvc
          %assign aProvidingService = providingServices.ProvidingService[i]
          %if aProvidingService.DworkIdx >= 0
            %assign dwRec = ::CompiledModel.DWorks.DWork[aProvidingService.DworkIdx]
            %assign dwName = ...
              FcnCGIRCGVarHelper(dwRec.VarGroupIdx[0], dwRec.VarGroupIdx[1], ...
              TLC_FALSE, GetBaseSystemIdx(), SLibDWorkWidth(dwRec), "", -1, ...
              "", 0, TLC_FALSE)
            %assign argName = "service%<argIdx>"
            %assign ppIf = SLibIfVariantConditionForm(dwRec.VariantCondition)
            %assign ppEndif = SLibEndIfVariantConditionForm(dwRec.VariantCondition)
            %<ppIf>
            %<dwName> = %<argName>;
            %<ppEndif>
            %assign argIdx = argIdx + 1
          %endif
        %endforeach
      %endif
    %endforeach
  %endwith
%endfunction
 
%%UtilityfunctionthatreturnsaDWorkpathforamodelblock's
%%serviceport
%%/-------------Givenamodelblock(aMdlBlk),aservice
%%|port(p2)andaserviceinthatport
%%p2|p1thisfunctionreturntheDWorkpath
%%===>|o===>fortheserviceportp1
%%|In1
%%|aMdlBlk
%%/-------------
 
%function SLibGetServiceDWorkInfoForMdl(aMdlBlk, aPort, aService) void
  %createrecord aRecord { DWorkPath ""; VariantCondition ""}
  %assign serviceDWorkPath = ""
  %if !ISEMPTY(aMdlBlk)
    %assign pairedServiceInChildMdl = ...
      SLibGetPairedServiceAtMdlBoundary(aPort, aService, aMdlBlk)
    %if !ISEMPTY(pairedServiceInChildMdl)
      %assign dworkPath = SLibGetChildModelServiceDWorkPath(pairedServiceInChildMdl)
      %if !ISEMPTY(dworkPath)
        %assign modelBlkDWork = SLibGetModelBlockStructDWorkArgIfExists(aMdlBlk,"RegistrationFcn")
        %if !ISEMPTY(modelBlkDWork)
          %assign serviceDWorkPath = modelBlkDWork + "." + dworkPath
        %else
          %assign serviceDWorkPath = dworkPath
        %endif
      %endif
      %assign aRecord.DWorkPath = serviceDWorkPath
      %assign aRecord.VariantCondition = pairedServiceInChildMdl.DWorkVariantCondition
    %endif
  %endif
  %return aRecord
%endfunction
 
%function SLibInitServiceToNULL(thisService, mdlDWorkArg) Output
  %assign dworkPath = SLibGetChildModelServiceDWorkPath(thisService)
  %assign serviceDWorkPath = dworkPath
  %if !ISEMPTY(mdlDWorkArg)
    %assign serviceDWorkPath = mdlDWorkArg + "." + serviceDWorkPath
  %endif
  %assign serviceFcnPtr = serviceDWorkPath + "." + thisService.Name
  %assign nullDef = SLibGetNullDefinitionFromTfl()
  %<serviceFcnPtr> = %<nullDef>;
  %assign hostPtr = serviceDWorkPath + ".host"
  %<hostPtr> = %<nullDef>;
%endfunction
 
%function SLibDumpServicePortUnconnectedMdlPortsInit() Output
  %% This handles unconnected model service ports
  %% -------/ /--------------
  %% | |
  %% ===>o |> >| o===>
  %% Out1 |p1 p2| In1
  %% -------/ /-------------
  %%
  %% Here we assign DWork for Out1 and In1 to NULL
  %%
  %if GenerateClassInterface || !SLibServicePortsExist()
    %return
  %endif
  %with ServicePortInfoMap
    %foreach portIdx = NumServicePorts
      %assign thisPort = ServicePort[portIdx]
      %assign aSID = thisPort.SID
      %assign portIdx = thisPort.ServicePortIdx
      %assign requestingServices = thisPort.RequestingServices
      %assign providingServices = thisPort.ProvidingServices
      %if ISEMPTY(requestingServices) && ISEMPTY(providingServices)
        %% We have a service port that is not providing or
        %% requesting a service. This indicates that the port
        %% is unconnected
        %assign mdlBlk = SLibGetMdlBlockFromSID(aSID)
        %if !ISEMPTY(mdlBlk)
          %assign mdlDWorkArg = SLibGetModelBlockStructDWorkArgIfExists(mdlBlk,"RegistrationFcn")
          %assign pairedPort = SLibGetPairedServicePort(portIdx, TLC_FALSE, thisPort.ServicePortType, mdlBlk)
          %if ISFIELD(pairedPort, "RequestingService")
            %assign requestingServices = pairedPort.RequestingService
            %assign numRequestingSvc = SIZE(requestingServices)[1]
            %if numRequestingSvc > 0
              %if numRequestingSvc == 1
                %assign thisService = requestingServices
                %<SLibInitServiceToNULL(thisService, mdlDWorkArg)>
              %else
                %foreach svcIdx=numRequestingSvc
                  %assign thisService = requestingServices[svcIdx]
                  %<SLibInitServiceToNULL(thisService, mdlDWorkArg)>
                %endforeach
              %endif
            %endif
          %endif
          %if ISFIELD(pairedPort, "ProvidingService")
            %assign providingServices = pairedPort.ProvidingService
            %assign numProvidingSvc = SIZE(providingServices)[1]
            %if numProvidingSvc > 0
              %if numProvidingSvc == 1
                %assign thisService = providingServices
                %<SLibInitServiceToNULL(thisService, mdlDWorkArg)>
              %else
                %foreach svcIdx=numProvidingSvc
                  %assign thisService = providingServices[svcIdx]
                  %<SLibInitServiceToNULL(thisService, mdlDWorkArg)>
                %endforeach
              %endif
            %endif
          %endif
        %endif
      %endif
    %endforeach
  %endwith
%endfunction
 
%function SLibDumpServicePortConnectionsInit() Output
   
  %<SLibDumpServicePortUnconnectedMdlPortsInit()>
   
  %% This handles the direct connection between two models
  %% -------/ /--------------
  %% | |
  %% ===>o |======>| o===>[queue]
  %% Out1 |p1 p2| In1
  %% -------/ /-------------
  %%
  %% Here we assign DWork for Out1 to the service and host of
  %% the service provider. We handle the delegation and
  %% no delegation cases here.
  %%
  %if GenerateClassInterface || !SLibServicePortsExist()
    %return
  %endif
  %with ServicePortInfoMap
    %foreach portIdx = NumServicePorts
      %assign thisPort = ServicePort[portIdx]
      %assign aSID = thisPort.SID
 
      %assign requestingServices = thisPort.RequestingServices
      %if !ISEMPTY(requestingServices)
        %assign numRequestingSvc = SIZE(requestingServices.RequestingService)[1]
        %foreach i=numRequestingSvc
          %assign aRequestingService = requestingServices.RequestingService[i]
          %assign requesterBlk = SLibGetMdlBlockFromSID(thisPort.SID)
          %% Requester ports must be on a modelref boundary (p1 above)
          %if !ISEMPTY(requesterBlk)
            %% Get the DWork path from the requester side's paired port (Out1 above)
            %assign requesterDWorkArg = SLibGetModelBlockStructDWorkArgIfExists(requesterBlk,"RegistrationFcn")
            %assign pairedRequesterServiceInChildMdl = SLibGetPairedServiceAtMdlBoundary(thisPort, aRequestingService, requesterBlk)
            %assign dworkPath = SLibGetChildModelServiceDWorkPath(pairedRequesterServiceInChildMdl)
            %assign serviceDWorkPath = dworkPath
            %if !ISEMPTY(requesterDWorkArg)
              %assign serviceDWorkPath = requesterDWorkArg + "." + serviceDWorkPath
            %endif
               
            %if !ISEMPTY(serviceDWorkPath)
              %if aRequestingService.DworkIdx < 0
                %% Would not expect requesting port to have a DWork since it is not an Outport or Inport.
                %% Get the service connected to the requester (p2 above).
                %assign pairedServiceAndPort = SLibGetPairedServiceAndPort(thisPort, aRequestingService)
                %if !ISEMPTY(pairedServiceAndPort.port) && !ISEMPTY(pairedServiceAndPort.service)
                  %assign providerBlk = SLibGetMdlBlockFromSID(pairedServiceAndPort.port.SID)
                  %% Make sure the paired service is also on a modelref boundary
                  %if !ISEMPTY(providerBlk)
                    %% Get the DWork arg for the provider side's paired port (In1 above)
                    %assign pairedProviderServiceInChildMdl = ...
                      SLibGetPairedServiceAtMdlBoundary(pairedServiceAndPort.port, ...
                      pairedServiceAndPort.service, ...
                      providerBlk)
                    %if !ISEMPTY(pairedProviderServiceInChildMdl)
                      %assign providerDWorkArg = SLibGetModelBlockStructDWorkArgIfExists(providerBlk,"RegistrationFcn")
                      %if !ISEMPTY(pairedProviderServiceInChildMdl.DelegatedDworkPath)
                        %% Handle the delegation case (provider model will forward the service request to one of its child models.
                        %% -------/ /-------------
                        %% | | /------
                        %% | | |
                        %% ===>o |======>| o===>|o===> Here we set Out1's service port dwork to p3's values
                        %% Out1 |p1 p2| In1 |In3 (p3)
                        %% | | /------
                        %% -------/ /-------------
                        %% Grab the service function and host from the delegated fields of the port
                        %assign serviceFcnPtrRHS = pairedProviderServiceInChildMdl.DelegatedServiceName
                        %if !ISEMPTY(providerDWorkArg)
                          %assign hostRHS = ...
                            "(void *)&(" + providerDWorkArg + "." + ...
                            pairedProviderServiceInChildMdl.DelegatedHost + ")"
                        %else
                          %assign hostRHS = SLibGetNullDefinitionFromTfl()
                        %endif
                      %else
                        %% Handle the non-delegation case (provider model will provide the service directly).
                        %% Grab the service function from the provider model's port
                        %assign serviceFcnPtrRHS = pairedProviderServiceInChildMdl.CGFcnName
                        %if !ISEMPTY(providerDWorkArg)
                          %assign hostRHS = "&" + providerDWorkArg
                        %else
                          %assign hostRHS = SLibGetNullDefinitionFromTfl()
                        %endif
                      %endif
                    %else
                      %continue
                    %endif
                  %else
                    %continue
                  %endif
                %else
                  %continue
                %endif
              %endif
              %assign serviceFcnPtr = serviceDWorkPath + "." + aRequestingService.Name
              %<serviceFcnPtr> = %<serviceFcnPtrRHS>;
              %assign hostPtr = serviceDWorkPath + ".host"
              %<hostPtr> = %<hostRHS>;
            %endif
          %endif
        %endforeach %% numRequestingSvc
      %endif %% !ISEMPTY(aRequestingService)
       
    %endforeach %% NumServicePorts
  %endwith %%ServicePortInfoMap
%endfunction
 
%function SLibDumpServicePortProvidersInit() Output
  %% Handle the provider side of the modelref hierarchy
  %% /-------------
  %% | /------
  %% | |
  %%===>| o===>|o===> Here we copy child model's dwork
  %% p2| In1 |In2 (p3) to the parent model (In1 = In2)
  %% | /------
  %% /-------------
  %if GenerateClassInterface || !SLibServicePortsExist() || SLibAutosarCompliant()
    %return
  %endif
  %with ServicePortInfoMap
    %foreach portIdx = NumServicePorts
      %assign thisPort = ServicePort[portIdx]
      %assign mdlBlk = SLibGetMdlBlockFromSID(thisPort.SID)
 
      %assign requestingServices = thisPort.RequestingServices
      %if !ISEMPTY(requestingServices)
        %assign numRequestingSvc = SIZE(requestingServices.RequestingService)[1]
        %foreach i=numRequestingSvc
          %assign aRequestingService = requestingServices.RequestingService[i]
          %if ISEMPTY(mdlBlk)
            %if aRequestingService.DworkIdx >= 0 && ...
              (thisPort.ServicePortType == "SVC_OUT_PORT" || thisPort.ServicePortType == "SVC_IN_PORT")
              %assign dwRec = ::CompiledModel.DWorks.DWork[aRequestingService.DworkIdx]
              %assign dwName = ...
                FcnCGIRCGVarHelper(dwRec.VarGroupIdx[0], dwRec.VarGroupIdx[1], ...
                TLC_FALSE, GetBaseSystemIdx(), SLibDWorkWidth(dwRec), "", -1, ...
                "", 0, TLC_FALSE)
              %assign ppIf = SLibIfVariantConditionForm(dwRec.VariantCondition)
              %assign ppEndif = SLibEndIfVariantConditionForm(dwRec.VariantCondition)
              %if aRequestingService.DelegatedDworkIdx >= 0
                %assign delegatedBlk = SLibGetMdlBlockFromSID(aRequestingService.DelegatedSID)
                %if !ISEMPTY(delegatedBlk)
                  %assign pairedService = SLibGetPairedServiceHelper(aRequestingService.DelegatedPortIdx, aRequestingService.Name, TLC_TRUE, thisPort.ServicePortType, delegatedBlk)
                  %assign dworkPath = SLibGetChildModelServiceDWorkPath(pairedService)
                  %if !ISEMPTY(dworkPath)
                    %assign mdlBlockStructArg = SLibGetModelBlockStructDWorkArgIfExists(delegatedBlk,"RegistrationFcn")
                    %if !ISEMPTY(mdlBlockStructArg)
                      %assign serviceDWorkPath = mdlBlockStructArg + "." + dworkPath
                      %<ppIf>
                      %<serviceDWorkPath>.host = (void *)&(%<mdlBlockStructArg>);
                      %<dwName> = %<serviceDWorkPath>;
                      %<ppEndif>
                    %else
                      %assign nulldef = SLibGetNullDefinitionFromTfl()
                      %<ppIf>
                      %<dworkPath>.host = %<nulldef>;
                      %<dwName> = %<dworkPath>;
                      %<ppEndif>
                    %endif
                  %endif
                %endif
              %else
                %<ppIf>
                %<dwName>.%<aRequestingService.Name> = %<aRequestingService.CGFcnName>;
                %<ppEndif>
              %endif
            %endif
          %endif
        %endforeach %% numRequestingSvc
      %endif %% !ISEMPTY(aRequestingService)
       
      %% In this case the service provider is in the bottom model and the top model
      %% which has the requesters needs to init the provider's host ptr.
      %assign providingServices = thisPort.ProvidingServices
      %if !ISEMPTY(providingServices)
        %assign numProvidingSvc = SIZE(providingServices.ProvidingService)[1]
        %foreach i=numProvidingSvc
          %assign aProvidingService = providingServices.ProvidingService[i]
          %assign dworkIdx = aProvidingService.DworkIdx
          %if dworkIdx < 0
            %if !ISEMPTY(mdlBlk)
              %assign pairedServiceAndPort = SLibGetPairedServiceAndPort(thisPort, aProvidingService)
              %if ISEMPTY(pairedServiceAndPort.port) || ISEMPTY(pairedServiceAndPort.service) || ...
                pairedServiceAndPort.service.DelegatedDworkIdx < 0
                %% Don't initialize host pointer here if delegation
                %assign pairedServiceInChildMdl = ...
                  SLibGetPairedServiceAtMdlBoundary(thisPort, aProvidingService, mdlBlk)
                %if !ISEMPTY(pairedServiceInChildMdl)
                  %assign dworkPath = SLibGetChildModelServiceDWorkPath(pairedServiceInChildMdl)
                  %if !ISEMPTY(dworkPath) && ISEMPTY(pairedServiceInChildMdl.DelegatedSID)
                    %assign modelBlkDWork = SLibGetModelBlockStructDWorkArgIfExists(mdlBlk,"RegistrationFcn")
                    %if !ISEMPTY(modelBlkDWork)
                      %assign serviceDWorkPath = modelBlkDWork + "." + dworkPath
                      %assign hostPtr = serviceDWorkPath + ".host"
                      %<hostPtr> = (void *)&(%<modelBlkDWork>);
                    %else
                      %assign hostPtr = dworkPath + ".host"
                      %assign nulldef = SLibGetNullDefinitionFromTfl()
                      %<hostPtr> = %<nulldef>;
                    %endif
                  %endif
                %endif
              %endif
            %endif
          %endif
        %endforeach
      %endif %% !ISEMPTY(providingServices)
    %endforeach %% NumServicePorts
  %endwith %%ServicePortInfoMap
%endfunction
 
%function SLibDumpServicePortRequestersInit() Output
  %% Handle the requester side of the modelref hierarchy
  %% ---------------/
  %% -------/ |
  %% ==>o |====>o |===>
  %% Out1 | Out2|
  %% -------/ |
  %% ---------------/
  %%
  %% Here we assign DWork for Out1 to DWork for Out2
  %if GenerateClassInterface || !SLibServicePortsExist() || SLibAutosarCompliant()
    %return
  %endif
  %with ServicePortInfoMap
    %foreach portIdx = NumServicePorts
      %assign thisPort = ServicePort[portIdx]
      %assign providingServices = thisPort.ProvidingServices
      %if !ISEMPTY(providingServices)
        %assign numProvidingSvc = SIZE(providingServices.ProvidingService)[1]
        %foreach i=numProvidingSvc
          %assign aProvidingService = providingServices.ProvidingService[i]
          %assign dworkIdx = aProvidingService.DworkIdx
          %if dworkIdx >= 0
            %% This handles the requester side delegation case (Out2 -> Out1)
            %% ---------------/
            %% -------/ |
            %% p1 | p2 |
            %% ==>o |====>o |===>
            %% Out1 | Out2|
            %% -------/ |
            %% ---------------/
            %%
            %% Here we assign DWork for Out1 to DWork for Out2
            %% (essentially service port p1 = p2)
            %assign dwRec = ::CompiledModel.DWorks.DWork[dworkIdx]
            %assign providerBlk = System[dwRec.SigSrc[0]].Block[dwRec.SigSrc[2]]
            %if (TYPE(providerBlk.Type) == "Identifier" && ...
              ((providerBlk.Type == "Outport") || (providerBlk.Type == "Opaque")))
              %if !ISEMPTY(aProvidingService.DelegatedSID)
                %assign mdlBlk = SLibGetMdlBlockFromSID(aProvidingService.DelegatedSID)
                %assign dwName = ...
                  FcnCGIRCGVarHelper(dwRec.VarGroupIdx[0], dwRec.VarGroupIdx[1], ...
                  TLC_FALSE, GetBaseSystemIdx(), SLibDWorkWidth(dwRec), "", -1, ...
                  "", 0, TLC_FALSE)
                %assign serviceDWorkInfo = SLibGetServiceDWorkInfoForMdl(mdlBlk, thisPort, aProvidingService)
                %assign serviceDWorkPath = serviceDWorkInfo.DWorkPath
                %assign serviceVC = serviceDWorkInfo.VariantCondition
                %assign ppIf = SLibIfVariantConditionForm(dwRec.VariantCondition)
                %assign ppEndif = SLibEndIfVariantConditionForm(dwRec.VariantCondition)
                %assign ppIfMdl = SLibIfVariantConditionForm(serviceVC)
                %assign ppEndifMdl = SLibEndIfVariantConditionForm(serviceVC)
                %<ppIf>
                %<ppIfMdl>
                %<serviceDWorkPath> = %<dwName>;
                %<ppEndifMdl>
                %<ppEndif>
              %endif
            %endif
          %else
            %% This handles the service provider to direct child requester case (Queue -> Out2)
            %% ---------------/
            %% -------/ p2 |
            %% ==>o |====>o |===>[Queue]
            %% Out1 | Out2|
            %% -------/ |
            %% ---------------/
            %%
            %% Here we assign DWork for Out2
            %% (essentially set service port p2 properties directly)
            %if !ISEMPTY(aProvidingService.PairedBlockSID)
              %assign pairedServiceAndPort = SLibGetPairedServiceAndPort(thisPort, aProvidingService)
              %assign pairedService = pairedServiceAndPort.service
              %assign pairedPort = pairedServiceAndPort.port
              %if !ISEMPTY(pairedService) && !ISEMPTY(pairedPort)
                %assign mdlBlk = SLibGetMdlBlockFromSID(pairedPort.SID)
                %assign providerMdlBlk = SLibGetMdlBlockFromSID(thisPort.SID)
                %% Don't do this initialization for two connecting model blocks. This will be
                %% handled by SLibDumpServicePortConnectionsInit
                %if !ISEMPTY(mdlBlk) && ISEMPTY(providerMdlBlk)
                  %assign serviceFcnPtrRHS = aProvidingService.CGFcnName
                  %assign serviceDWorkInfo = SLibGetServiceDWorkInfoForMdl(mdlBlk, pairedPort, pairedService)
                  %assign serviceDWorkPath = serviceDWorkInfo.DWorkPath
                  %assign serviceVC = serviceDWorkInfo.VariantCondition
                  %assign ppIfMdl = SLibIfVariantConditionForm(serviceVC)
                  %assign ppEndifMdl = SLibEndIfVariantConditionForm(serviceVC)
                  %assign serviceFcnPtr = serviceDWorkPath + "." + pairedService.Name
                  %<ppIfMdl>
                  %<serviceFcnPtr> = %<serviceFcnPtrRHS>;
                  %assign hostPtr = serviceDWorkPath + ".host"
                  %if IsModelReferenceTarget()
                    %% Parent is going to have to initialize host pointer
                    %% since this model doesn't know it's instance data
                    %% pointer.
                    %<hostPtr> = %<SLibGetNullDefinitionFromTfl()>;
                    %% Use -2 to indicate that delegaion info needs to
                    %% be fabricated and stored in the model interface
                    %% (in minfo)
                    %assign tmpRet = %<SETFIELD(aProvidingService,"DelegatedDworkIdx",-2)>
                  %else
                    %if RTMTypeIsNeeded()
                      %<hostPtr> = %<::tSimStruct>;
                    %else
                      %<hostPtr> = %<SLibGetNullDefinitionFromTfl()>;
                    %endif
                  %endif
                  %<ppEndifMdl>
                %endif
              %endif
            %endif
          %endif %% dworkIdx
        %endforeach %% numProvidingSvc
      %endif %% !ISEMPTY(providingServices)
    %endforeach %% NumServicePorts
  %endwith %%ServicePortInfoMap
%endfunction
 
%function SLibDumpServiceInitForChildModel(mdlBlk) Output
  %if GenerateClassInterface || !EXISTS(NumServicePorts)
    %return
  %endif
  %if mdlBlk.Type == "ModelReference"
    %assign interface = GetModelrefInterface(mdlBlk)
    %foreach portIdx = interface.NumServicePorts
      %assign thisPort = interface.ServicePort[portIdx]
      %if ISFIELD(thisPort, "ProvidingService")
        %assign providingServices = thisPort.ProvidingService
        %assign numProvidingSvc = SIZE(providingServices)[1]
        %if numProvidingSvc > 0
          %assign dwPrefix = interface.rtmAllocateInParent ? "." : ".rtdw."
          %if numProvidingSvc == 1
              %if providingServices.DelegatedDworkIdx == -2
                %assign modelBlkDWork = SLibGetModelBlockStructDWorkArgIfExists(mdlBlk,"RegistrationFcn")
                %if ISEMPTY(modelBlkDWork)
                  %continue
                %endif
                %assign serviceDWorkPath = modelBlkDWork + dwPrefix + providingServices.DelegatedDworkPath
                %assign hostPtr = serviceDWorkPath + ".host"
                %<hostPtr> = (void *)&(%<modelBlkDWork>);
              %endif
            %else
              %foreach svcIdx=numProvidingSvc
                %assign thisService = providingServices[svcIdx]
                %if thisService.DelegatedDworkIdx == -2
                  %assign modelBlkDWork = SLibGetModelBlockStructDWorkArgIfExists(mdlBlk,"RegistrationFcn")
                  %if ISEMPTY(modelBlkDWork)
                    %continue
                  %endif
                %assign serviceDWorkPath = modelBlkDWork + dwPrefix + thisService.DelegatedDworkPath
                %assign hostPtr = serviceDWorkPath + ".host"
                %<hostPtr> = (void *)&(%<modelBlkDWork>);
              %endif
            %endforeach
          %endif
        %endif
      %endif
    %endforeach
  %endif
%endfunction
 
%%Initializethismodel'sserviceDWorkforservicesprovidedbythismodel
%function SLibDumpServicePortSelfInit() Output
  %if GenerateClassInterface || !SLibServicePortsExist()
    %return
  %endif
  %with ServicePortInfoMap
    %foreach portIdx = NumServicePorts
      %assign thisPort = ServicePort[portIdx]
      %assign aSID = thisPort.SID
      %assign requestingServices = thisPort.RequestingServices
      %if !ISEMPTY(requestingServices)
        %assign numRequestingSvc = SIZE(requestingServices.RequestingService)[1]
        %foreach i=numRequestingSvc
          %assign aRequestingService = requestingServices.RequestingService[i]
          %if aRequestingService.DworkIdx >= 0 && aRequestingService.DelegatedDworkIdx < 0
            %assign dwRec = ::CompiledModel.DWorks.DWork[aRequestingService.DworkIdx]
            %assign providerBlk = System[dwRec.SigSrc[0]].Block[dwRec.SigSrc[2]]
            %if (TYPE(providerBlk.Type) == "Identifier" && providerBlk.Type == "Inport")
              %assign dworkvar = providerBlk.Identifier + "_" + dwRec.Name
              %assign serviceFcnPtr = LibGetDWorkStruct() + "." + dworkvar + "." + aProvidingService.Name
              %assign serviceFcnPtrRHS = aRequestingService.CGFcnName
              %assign nulldef = SLibGetNullDefinitionFromTfl()
              %assign hostPtr = LibGetDWorkStruct() + "." + dworkvar + ".host"
              %assign ppIf = SLibIfVariantConditionForm(dwRec.VariantCondition)
              %assign ppEndif = SLibEndIfVariantConditionForm(dwRec.VariantCondition)
              %<ppIf>
              %<serviceFcnPtr> = %<serviceFcnPtrRHS>;
              %<hostPtr> = %<nulldef>;
              %<ppEndif>
            %endif
          %endif
        %endforeach %% numRequestingSvc
      %endif %% !ISEMPTY(aRequestingService)
    %endforeach %% NumServicePorts
  %endwith %%ServicePortInfoMap
%endfunction
 
%endif %% _SERVICELIB_
%%[EOF]servicelib.tlc