%%
%%
%%
%%
%%Copyright1994-2010TheMathWorks,Inc.
%%
%%Abstract:
%%LibrarytosupportthenotionofanrtModelobject.
%%CurrentlyalsocontainsroutinesforrootSimStruct
%%
 
%if EXISTS("_CHILDSFCNLIB_") == 0
%assign _CHILDSFCNLIB_ = 1
 
%%Function:SLibGenChildSfcnTermMemFreeCode===================================
%%Abstract:
%%DumpmemoryfreecodeinMdlTerminatewhenweareusingUsingMalloc
%%
%function SLibGenChildSfcnTermMemFreeCode(s) Output
  %assign isSfcnCF = (CodeFormat == "S-Function")
  %assign nulldef = SLibGetNullDefinitionFromTfl()
  if( %<s> != %<nulldef> ) {
    %%
    %% Level independent allocation
    %%
    rt_FREE(ssGetSampleTimePtr(%<s>));
    rt_FREE(ssGetOffsetTimePtr(%<s>));
    rt_FREE(ssGetSampleTimeTaskIDPtr(%<s>));
    %assign numArgs = Parameters[0] / 2
    %if numArgs > 0
      %if isSfcnCF
    %%
    %% free params not tunable array
    %%
    %if LibSFunctionLevel() == "Level2"
      #if defined(MATLAB_MEX_FILE)
      {
        uint_T *attribs = ...
          ssGetSFcnParamAttribsPtr(%<s>);
         
        mxFree(attribs);
      }
      #endif
    %endif %% SFunctionLevel == "Level2"
    %%
    %% free MATLAB versions of mxArray
    %%
    #if defined(MATLAB_MEX_FILE)
    {
      %foreach argIdx = numArgs
        %%assign paramIdx =
        %assign paramVal = "P%"
        %if SLibGetBlockParameterStorageClass(%<paramVal>) == "Auto_SFCN"
          %% S-Function parameters marked as tunable are allocated and
          %% freed by Simulink and don't need to be handled by the S-Function
          %% termination function
        %else
          {
        mxDestroyArray(_ssGetSFcnParam(%<s>, %<argIdx>));
          }
        %endif
      %endforeach
    }
    #endif
      %endif %% isSfcnCF
       
      %%
      %% Unconditionally free param ptr array
      %%
      {
    mxArray **ptr = (mxArray **) ssGetSFcnParamsPtr(%<s>);
    rt_FREE(ptr);
      }
    %endif %% numArgs > 0
     
    %if NumSFcnSysOutputCallDsts > 0
      rt_FREE(ssGetCallSystemOutputPtr(%<s>));
      rt_FREE(ssGetCallSystemOutputArg1List(%<s>));
      rt_FREE(ssGetCallSystemOutputArg2List(%<s>));
      rt_FREE(ssGetCallSystemOutputFcnList(%<s>));
    %endif
    %%
    %% Level dependent allocation
    %%
    %if ParamSettings.FunctionLevel == 1
      %%
      %% Level 1
      %%
      %assign usingUPtrs = (ParamSettings.UsingUPtrs == "yes")
      %assign inputsContiguous = ...
    (ParamSettings.InputContiguous == "yes")
      %if usingUPtrs
    {
      real_T **ptr = (real_T **) ssGetUPtrs(%<s>);
      rt_FREE(ptr);
    }
      %elseif !inputsContiguous
    {
      real_T *ptr = (real_T *) ssGetU(%<s>);
      rt_FREE(ptr);
    }
      %endif
      %if StatesDiscontiguous
    {
      real_T *ptr = (real_T *) ssGetContStates(%<s>);
      rt_FREE(ptr);
    }
      %endif
      %% D-Work
      %if NumDWork > 0
    rt_FREE(ssGetSFcnDWork(%<s>));
      %endif
    %else
      %%
      %% Level 2
      %%
      %if GenRTModel
    /* Destroy the blkInfo2 ptr */
    {
      struct _ssBlkInfo2 *blkInfo2 = ssGetBlkInfo2Ptr(%<s>);
      rt_FREE(blkInfo2);
    }
      %endif
      /* Destroy model methods 4 */
      {
        struct _ssSFcnModelMethods4 *methods4 = ssGetModelMethods4(%<s>);
        rt_FREE(methods4);
      }
      /* Destroy model methods 3 */
      {
        struct _ssSFcnModelMethods3 *methods3 = ssGetModelMethods3(%<s>);
        rt_FREE(methods3);
      }
      /* Destroy model methods 2 */
      {
        struct _ssSFcnModelMethods2 *methods2 = ssGetModelMethods2(%<s>);
        rt_FREE(methods2);
      }
      /* Destroy state auxilliary information */
      {
        struct _ssStatesInfo2 *statesInfo2 = ssGetStatesInfo2(%<s>);
        ssPeriodicStatesInfo* periodicStatesInfo = ssGetPeriodicStatesInfo(%<s>);
        ssJacobianPerturbationBounds *jacobianPerturbationBounds = ssGetJacobianPerturbationBounds(%<s>);
        rt_FREE(jacobianPerturbationBounds);
        rt_FREE(periodicStatesInfo);
        rt_FREE(statesInfo2);
      }
 
       
      %foreach ipIdx = NumDataInputPorts
    {
      %if ParamSettings.UsingUPtrs[ipIdx] == "yes"
        void **ptr = (void**) /
        ssGetInputPortSignalPtrs(%<s>, %<ipIdx>);
        rt_FREE(ptr);
      %endif
      %assign nDims = LibBlockInputSignalNumDimensions(ipIdx)
      %if nDims >= matrixDimensionThreshhold && UsingMalloc
        %if !isSfcnCF
          rt_FREE(ssGetInputPortDimensions(%<s>, %<ipIdx>));
        %else
          {
        int_T *dimensions = /
        ssGetInputPortDimensions(%<s>, %<ipIdx>);
        #if defined(MATLAB_MEX_FILE)
        if (dimensions != %<nulldef>) {
          utFree(dimensions);
          dimensions = %<nulldef>;
        }
        #else
        rt_FREE(dimensions);
        #endif
          }
        %endif
      %endif
    }
      %endforeach
      %foreach opIdx = NumDataOutputPorts
    %assign nDims = LibBlockOutputSignalNumDimensions(opIdx)
    %if nDims >= matrixDimensionThreshhold && UsingMalloc
      %if !isSfcnCF
        rt_FREE(ssGetOutputPortDimensions(%<s>, %<opIdx>));
      %else
        {
          int_T *dimensions = /
          ssGetOutputPortDimensions(%<s>, %<opIdx>);
          #if defined(MATLAB_MEX_FILE)
          if (dimensions != %<nulldef>) {
        utFree(dimensions);
        dimensions = %<nulldef>;
          }
          #else
          rt_FREE(dimensions);
          #endif
        }
      %endif
    %endif
      %endforeach
      %%
      %% Need to add these macros to simstruc.h
      %%
      rt_FREE(ssGetPortInfoForInputs(%<s>));
      rt_FREE(ssGetPortInfoForOutputs(%<s>));
      %%
      %% D-Work
      %if NumDWork > 0
    rt_FREE(ssGetSFcnDWork(%<s>));
      %endif
    %endif
  }
%endfunction %% SLibGenChildSfcnTermMemFreeCode
 
 
%%Function:SLibCacheRTCallSys================================================
%%Abstract:
%%Cachert_CallSys(),rtEnableSys()andrt_DiableSysusedbynon-inlined
%%S-Functionswhichmakefunctioncalls.
%%
%function SLibCacheRTCallSys() void
  %if CodeFormat != "S-Function" && !IsModelReferenceSimTarget() && ::CompiledModel.NumChildSFunctions > 0
    %foreach childIdx = NumChildSFunctions
      %assign thisBlock = ChildSFunctionList[childIdx]
      %with thisBlock
    %if NumSFcnSysOutputCallDsts > 0 || ...
      (ISFIELD(ParamSettings,"RTWGenerated") && ParamSettings.RTWGenerated == 1)
      %% Need Helper functions
      %<LibGenMathFcnCall("sfcnhelpers", FcnGetDataTypeIdFromName("double"), ...
        "sizeof(real_T)", "")>
      %break
    %endif
      %endwith %%thisBlock
    %endforeach %%NumChildSFunctions
  %endif
%endfunction
 
 
%%Function:SLibGenERTNonInlinedSFcnsSubStruct===============================
%%Abstract:
%%Generatethesubstructureinthereal-timemodelrtM.NonInlinedSFcns
%%
%%Localfunctionusedinthisfile
%function SLibGenERTNonInlinedSFcnsSubStruct() void
  %openfile tmpFcnBuf
 
  /*
   * NonInlinedSFcns:
   * The following substructure contains information regarding
   * non-inlined s-functions used in the model.
   */
  struct {
    %% Fixed non-inlined sfunction elements
    %if !IsModelReferenceForASimstructBasedTarget()
      %if IsModelReferenceTarget()
        RTWSfcnInfo *sfcnInfo;
      %else
        RTWSfcnInfo sfcnInfo;
      %endif
    %endif
    time_T *taskTimePtrs[%<NumSampleTimes>];
    %% If only submodels contain non-inlined s-functions,
    %% we only need the sfcnInfo
    %if ::CompiledModel.NumChildSFunctions > 0
      SimStruct childSFunctions[%<NumChildSFunctions>];
      SimStruct *childSFunctionPtrs[%<NumChildSFunctions>];
      struct _ssBlkInfo2 blkInfo2[%<NumChildSFunctions>];
      struct _ssSFcnModelMethods2 methods2[%<NumChildSFunctions>];
      struct _ssSFcnModelMethods3 methods3[%<NumChildSFunctions>];
      struct _ssSFcnModelMethods4 methods4[%<NumChildSFunctions>];
      struct _ssStatesInfo2 statesInfo2[%<NumChildSFunctions>];
      ssPeriodicStatesInfo periodicStatesInfo[%<NumChildSFunctions>];
       
      struct _ssPortInfo2 inputOutputPortInfo2[%<NumChildSFunctions>];
       
      %%
      %% Dynamic non-inlined sfunction elements
      %%
      %foreach childIdx = NumChildSFunctions
        struct {
          %assign thisBlock = ChildSFunctionList[childIdx]
          %with thisBlock
            %assign sfuncName = ParamSettings.FunctionName
            %assign numSfcnSampleTimes = SIZE(TID, 1)
            time_T sfcnPeriod[%<numSfcnSampleTimes>];
            time_T sfcnOffset[%<numSfcnSampleTimes>];
            int_T sfcnTsMap[%<numSfcnSampleTimes>];
            %if NumDataInputPorts > 0
              struct _ssPortInputs inputPortInfo[%<NumDataInputPorts>];
              %% Unit information
              struct _ssInPortUnit inputPortUnits[%<NumDataInputPorts>];
              %% CoSim attribute
              struct _ssInPortCoSimAttribute inputPortCoSimAttribute[%<NumDataInputPorts>];
            %endif
            %%
            %% InputPort Info
            %assign num_vardims_inports = 0
            %foreach ipIdx = NumDataInputPorts
              %assign ip = DataInputPort[ipIdx]
              %assign dtype = SLibGetRecordDataTypeName(ip,"")
              %assign width = LibBlockInputSignalWidth(ipIdx)
              %assign dims = LibBlockInputSignalDimensions(ipIdx)
              %assign nDims = LibBlockInputSignalNumDimensions(ipIdx)
              %switch ParamSettings.FunctionLevel
                %case 1
                  %if ParamSettings.UsingUPtrs == "yes"
                    real_T const *UPtrs[%<width>];
                  %endif
                  %break
                %case 2
                  %if ParamSettings.UsingUPtrs[ipIdx] == "yes"
                    real_T const *UPtrs%<ipIdx>[%<width>];
                  %endif
                  %break
              %endswitch
              %if nDims >= matrixDimensionThreshhold
                int_T iDims%<ipIdx>[%<nDims>];
              %endif
              %if LibGetIsInputPortVarDims(ipIdx)
                %assign num_vardims_inports = num_vardims_inports + 1
              %endif
            %endforeach %%NumDataInputPorts
            %if num_vardims_inports > 0
              struct _ssInPortVarDims inputPortCurrentDims[%<num_vardims_inports>];
            %endif
            %%
            %% OutputPort Info
            %if NumDataOutputPorts > 0
              struct _ssPortOutputs outputPortInfo[%<NumDataOutputPorts>];
              %% Unit information
              struct _ssOutPortUnit outputPortUnits[%<NumDataOutputPorts>];
              %% CoSim attribute
              struct _ssOutPortCoSimAttribute outputPortCoSimAttribute[%<NumDataOutputPorts>];
            %endif
            %assign num_vardims_outports = 0
            %foreach opIdx = NumDataOutputPorts
              %assign oNumDims = LibBlockOutputSignalNumDimensions(opIdx)
              %if %<oNumDims> >= matrixDimensionThreshhold
                int_T oDims%<opIdx>[%<oNumDims>];
              %endif
              %if LibGetIsOutputPortVarDims(opIdx)
                %assign num_vardims_outports = num_vardims_outports + 1
              %endif
            %endforeach %%NumDataOutputPorts
             
            %if num_vardims_outports > 0
              struct _ssOutPortVarDims outputPortCurrentDims[%<num_vardims_outports>];
            %endif
             
            %%
            %% States: level-1 s-functions with discontinuous states
            %if ParamSettings.FunctionLevel == 1
              %assign numDiscStates = DiscStates[0]
              %assign numContStates = ContStates[0]
              %assign nStates = numDiscStates + numContStates
              %if (nStates > 0) && (StatesDiscontiguous == 1)
                real_T X[%<nStates>];
              %endif
            %endif
            %%
            %% Parameters
            %assign numArgs = Parameters[0] / 2
            %if numArgs > 0
              %if LibSFunctionLevel() == "Level2"
                uint_T attribs[%<numArgs>];
              %endif
              mxArray *params[%<numArgs>];
            %endif
            %%
            %% DWork
            %assign numDWorks = thisBlock.NumDWork
            %if numDWorks > 0
              struct _ssDWorkRecord dWork[%<numDWorks>];
              struct _ssDWorkAuxRecord dWorkAux[%<numDWorks>];
            %endif
            %%
            %% Function calls
            %if NumSFcnSysOutputCallDsts > 0
              %assign pZeroWidth = LibBlockOutputSignalWidth(0)
              int_T callSysOutputs[%<pZeroWidth>];
              void *callSysArgs1[%<pZeroWidth>];
              int_T callSysArgs2[%<pZeroWidth>];
              %if IsModelReferenceSimTarget()
                %% The Model Reference Simulation Target doesn't support
                %% Initialization function pointers
                SysOutputFcn callSysFcns[%<3*pZeroWidth>];
              %else
                SysOutputFcn callSysFcns[%<4*pZeroWidth>];
              %endif
            %endif
          } Sfcn%<childIdx>;
        %endwith %%thisBlock
      %endforeach %%NumChildSFunctions
    %endif %%NumChildSFunctions > 0
  } /
  %closefile tmpFcnBuf
  %return tmpFcnBuf
%endfunction
 
%endif %% _CHILDSFCNLIB_
 
%%[EOF]childsfcnlib.tlc