%%
%%
%%Copyright1994-2019TheMathWorks,Inc.
%%
%%Abstract:
%%ThisTLClibraryfilecontainsallthefunctionsrequiredforaccessing
%%blockparameters.
%%
 
%if EXISTS("_PARAMLIB_") == 0
%assign _PARAMLIB_ = 1
 
%%Function:SLibGetValueFromParamRec==========================================
%%Abstract:
%%Getvalueofaparameterfromtheparameterrecord.Foraparameterinside
%%aForEachsubsystemwhichhaspartitionedmaskparameter,theparameter
%%recordcontainsanarrayofvalues.ValueAccessIdxisusedtoindexthe
%%array
%%
%function SLibGetValueFromParamRec(param, ordinalValuesForEnums)
  %assign dtID = LibGetRecordDataTypeId(param)
  %if !ISFIELD(param, "NumPrmValues") || param.NumPrmValues == 1
    %if ordinalValuesForEnums && LibIsEnumDataType(dtID)
      %if ISFIELD(param, "OrdinalValue")
        %return param.OrdinalValue
      %else
        %assert ISEQUAL(param.Name, "From Workspace Data")
        %assign prmValue = param.Value
      %endif
    %else
      %assign prmValue = param.Value
    %endif
  %else
    %if ISFIELD(param, "ValueAccessIdx")
      %% param may have different values for different iterations in a For-Each subsystem.
      %% ValueAccessIdx is a temporary field served as an iteration index
      %assign prmValue = param.Values[param.ValueAccessIdx].Value
    %else
      %assign prmValue = param.Values[0].Value
    %endif
  %endif
 
  %if ordinalValuesForEnums && LibIsEnumDataType(dtID)
    %% Get ordinal values from underlying numeric values
    %assign nRows = SIZE(prmValue, 0)
    %assign nCols = SIZE(prmValue, 1)
    %assign width = nRows * nCols
    %foreach idx = width
      %assign prmValue[idx] = SLibGetEnumTypeIndexFromValue(dtID, prmValue[idx])
    %endforeach
  %endif
   
  %return prmValue
%endfunction
 
%%Function:SLibGetWidthOfValueFromParamRec===================================
%%Abstract:
%%Getwidthofvalueofaparameterfromtheparameterrecord.
%%
%function SLibGetWidthOfValueFromParamRec(param)
  %assign prmSize = SLibGetSizeOfValueFromParamRec(param)
  %return prmSize[0] * prmSize[1]
%endfunction
 
%%Function:SLibGetSizeOfValueFromParamRec====================================
%%Abstract:
%%Getsizeofvalueofaparameterfromtheparameterrecord.
%%Resultisa2-elementvector:[nRows,nCols]
%%
%function SLibGetSizeOfValueFromParamRec(param)
  %assign prmValue = SLibGetValueFromParamRec(param, TLC_FALSE)
  %return SIZE(prmValue)
%endfunction
 
%%Function:SLibGetTypeOfValueFromParamRec====================================
%%Abstract:
%%GetTLCtypeofvalueofaparameterfromtheparameterrecord.
%%
%function SLibGetTypeOfValueFromParamRec(param)
  %assign prmValue = SLibGetValueFromParamRec(param, TLC_FALSE)
  %return TYPE(prmValue)
%endfunction
 
%function GetValueExpressionFromParamRec(param)
    %assign prmValue = ""
    %if ISFIELD(param, "ValueExpression")
        %assign prmValue = param.ValueExpression
    %endif
    %return prmValue
%endfunction
 
%%DocFunction{ParameterFunctions}:LibBlockParameter=========================
%%Abstract:
%%Basedontheparameterreference(param),theusercontrolvariable(ucv),
%%theloopcontrolvariable(lcv),thesignalindex(sigIdx),andthe
%%stateofparameterinlining,thisfunctionreturnstheappropriate
%%referencetoablockparameter.
%%
%%Thereturnedvalueisalwaysavalidrvalue(righthandsizeexpression
%%value).Forexample,
%%
%%.----+-------------------------------------------+------------------.
%%|Case|FunctionCall|MayProduce|
%%+----+-------------------------------------------+------------------+
%%|1|LibBlockParameter(Gain,"i",lcv,sigIdx)|rtP.blockname[i]|
%%|2|LibBlockParameter(Gain,"i",lcv,sigIdx)|rtP.blockname|
%%|3|LibBlockParameter(Gain,"",lcv,sigIdx)|p_Gain[i]|
%%|4|LibBlockParameter(Gain,"",lcv,sigIdx)|p_Gain|
%%|5|LibBlockParameter(Gain,"",lcv,sigIdx)|4.55|
%%|6|LibBlockParameter(Gain,"",lcv,sigIdx)|rtP.blockname.re|
%%|7|LibBlockParameter(Gain,"",lcv,sigIdx)|rtP.blockname.im|
%%`----+-------------------------------------------+------------------'
%%
%%Toillustratethebasicworkingsofthisfunction,assumeanon-complex
%%vectorsignalwhereGain[0]=4.55
%%
%%LibBlockParameter(Gain,"","i",0)
%%
%%.----+---------+-----------+--------+----------------+-----------.
%%|Case|Rolling|Inline|Type|Result|Required|
%%|||Parameter|||InMemory|
%%+----+---------+-----------+--------+----------------+-----------+
%%|1|0|1|scalar|4.55|no|
%%|2|1|1|scalar|4.55|no|
%%|3|0|1|vector|4.55|no|
%%|4|1|1|vector|p_Gain[i]|yes|
%%|||||||
%%|5|0|0|scalar|rtP.blk.Gain|no|
%%|6|1|0|scalar|rtP.blk.Gain|no|
%%|7|0|0|vector|rtP.blk.prm[0]|no|
%%|8|1|0|vector|p_Gain[i]|yes|
%%`----+---------+-----------+--------+----------------+-----------'
%%
%%Notecase4.Eventhoughinlineparameteristrue,theparametermust
%%beplacedinmemory(RAM)sinceit'saccessedinsideafor-loop.
%%
%%Note:
%%Thisfunctionalsosupportsexpressionswhenusedwithinlinedparameters
%%andparametertuning.
%%
%%Forexample,iftheparameterfieldhadtheMexpression'2*a',this
%%functionwillreturntheCexpression'(2*a)'.Thelistoffunctions
%%supportedbythisfunctionisdeterminedbythefunctions
%%FcnConvertNodeToExprandFcnConvertIdToFcn.Toenhancefunctionality,
%%augment/updateeitherofthesefunctions.
%%
%%Notethatcertaintypesofexpressionsarenotsupportedsuchasx*y
%%whereBOTHxandyarenon-scalars.
%%
%%SeetheSimulinkCoderdocumentationabouttunableparametersfor
%%moredetailsontheexactfunctionsandsyntaxthatissupported.
%%
%%Warning:
%%Neverusethisfunctiontoaccesstheaddressofaparameter,oryou
%%mayendupreferencinganumber(i.e.,&4.55)whentheparameteris
%%inlined.AvoidthissituationentirelyusingLibBlockParameterAddr().
%%
%function LibBlockParameter(param, ucv, lcv, sigIdx) void
 
  %% Determine the parameter's true size
  %assign prmSize = SLibGetSizeOfValueFromParamRec(param)
  %assign nRows = prmSize[0]
  %assign nCols = prmSize[1]
  %assign width = nRows * nCols
 
  %if SLibGetTypeOfValueFromParamRec(param) == "Matrix"
    %% exit if the parameter is a true matrix,
    %% i.e., has more than one row or columns.
    %if nRows > 1
      %assign errTxt = "Must access parameter %<param.Name> using "...
        "LibBlockMatrixParameter."
      %<LibBlockReportError([], errTxt)>
    %endif
  %endif
  %with ::CompiledModel
    %assign accSysIdx = BlockIdx[0]
    %assign parentSys = System[accSysIdx]
    %if LibSystemIsRoot(parentSys)
      %assign callSite = [%<accSysIdx>, 0, %<accSysIdx>, %]
    %else
      %assign callSite = parentSys.CallSites[0]
    %endif
  %endwith
  %assign str = FcnGenParamExprWithCast(param.Name, accSysIdx, accSysIdx,...
    callSite, param, ucv, lcv, sigIdx)
   
  %if str != ""
    %return SLibProcessSafeExpression(Name, ...
      (param.NeedParenthesis ? "(%<str>)" : str), 0)
  %else
    %return ""
  %endif
%endfunction %% LibBlockParameter
 
 
%%Function:FcnGetCanParmArg==================================================
%%Abstract:
%%Returnthecanonicalparameterargumentdefinitionforagivensystem
%%andparameterindex.Thisfunctionwillalsomarkthereturned
%%canonicalparameterargumentasaccessed,soitwillbepartorthe
%%argumentlistofthereusableparentsubsystem.
%%
%%sysIdx-Thesystemwherewearegeneratingthiscode.
%%prmIdx-indexoftheparameterthatisaccessed.
%%
%function FcnGetCanParmArg(sysIdx, prmIdx)
  %assign hStrSys = System[sysIdx].ReusedParentSystemIdx
  %<LibAccessCanPrmArg(hStrSys, prmIdx, "")>
  %if System[sysIdx].CrossNoArgFcnBound
    %<LibAccessCanPrmArg(hStrSys,prmIdx,"Global")>
  %endif
  %return System[hStrSys].Interface.CanonicalPrmArgDef[prmIdx]
%endfunction
 
%%Function:FcnGetDataTypeIdFromAST===========================================
%%Abstract:
%%RetrievethestoreddatatypeoftheexpressionrepresentedbyexprAST.
%%Thisfunctionassumesthattheexpressioncanonlybeeitheranidentifier,
%%orastructurefieldreference(e.g.foo.a.b).Thefunctionissueserrorif
%%neighteristhecase.
%%
%function FcnGetDataTypeIdFromAST(exprAST)
  %assign ASTNodePath = FcnGetDirectStructReferenceNode(exprAST)
  %assign varNode = ASTNodePath.Node
  %switch (varNode.Op)
    %case "M_ID"
      %assign var = ::CompiledModel.ModelParameters.Parameter[varNode.ModelParameterIdx]
      %assign dtId = var.OriginalDataTypeIdx
      %break
    %case "M_CANPRM_ID"
      %with Interface
        %assign var = CanonicalPrmArgDef[varNode.CanonicalPrmArgDefIdx]
        %assign dtId = var.OriginalDataTypeIdx
      %endwith
      %break
    %default
      %error "ASTNode must be M_ID or M_CANPRM_ID"
  %endswitch
   
  %if ASTNodePath.path != ""
    %% Dereference a structure, get the data type of the element
    %assign szPath = SIZE(ASTNodePath.pathElem, 1)
    %foreach n = szPath
      %assert (LibIsStructDataType(dtId))
      %assign elemName = ASTNodePath.pathElem[n].name
      %assign idx = SLibFindDataTypeElementIdxByName(dtId, elemName)
      %assert (idx>=0)
      %assign dtId = LibDataTypeElementDataTypeId(dtId, idx)
    %endforeach
  %endif
  %return (dtId)
%endfunction
 
%%Function:FcnGenParamExprWithCast===========================================
%%Abstract:
%%Generateanexpressionincludingafixed-pointcast(ifnecessary).
%%
%%accSysIdx-thesystemwheretheparameterisbeingused,typicallyit
%%actuallytheHStructDeclSystemIdxwheretheparameterisdeclared.
%%parentSysIdx-Thesystemwherewearegeneratingthiscode.
%%SeeAlso:FcnGenExpr
%%
%function FcnGenParamExprWithCast(pName, accSysIdx, parentSysIdx, cs, param, ucv, lcv, sigIdx)
   
  %assign paramAST = param.ASTNode
   
  %if ((paramAST.IsNonTerminal == 1) && ...
    (paramAST.ASTNode[0].IsNonTerminal == 0) && ...
    (paramAST.ASTNode[0].Op == "M_ID") && ...
    (LibGetRecordIdentifier(paramAST.ASTNode[0]) == "fixpt_cast"))
     
    %% This parameter requires a fixed-point cast
    %assert (paramAST.NumChildren == 4)
     
    %% Get the expression that is being cast
    %assign exprAST = paramAST.ASTNode[2]
    %assign string = ...
      FcnGenExpr(pName, accSysIdx, parentSysIdx, cs, exprAST, paramAST, ucv, lcv, sigIdx)
 
    %assign asStoredDtId = FcnGetDataTypeIdFromAST(exprAST)
    %assign asUsedDtId = param.OriginalDataTypeIdx
     
    %assign asStoredDT = FixPt_GetDataTypeFromIndex(asStoredDtId)
    %assign asUsedDT = FixPt_GetDataTypeFromIndex(asUsedDtId)
     
    %% Generate the expression with the fixed-point cast (if possible)
    %assign string = FixPt_Fix2Fix_Param_Expr(asUsedDT, string, asStoredDT)
  %else
    %assign string = ...
      FcnGenExpr(pName, accSysIdx, parentSysIdx, cs, paramAST, paramAST, ucv, lcv, sigIdx)
  %endif
  %return (string)
%endfunction %% FcnGenParamExprWithCast
 
%%Function:FcnIsParamSel====================================================
%%Abstract:
%%GivenarootASTNodeisthisaparameterarrayselection?
%%---------ASTNode---------
%%||||
%%Param'('Num')'
%%
%%whereParam='a'-parameteror'a.b.c'-directstructreference
%%
%function FcnIsParamSel(ASTNode) void
  %assign isArraySel = ASTNode.NumChildren == 4 && ...
                ASTNode.ASTNode[1].Op == "M_LRB" && ...
                ASTNode.ASTNode[3].Op == "M_RRB"
  %if isArraySel
    %assign ASTParamNode = ASTNode.ASTNode[0]
    %if ASTParamNode.Op == "Dot"
      %assign ASTNodePath = FcnGetDirectStructReferenceNode(ASTParamNode)
      %assign ASTParamNode = ASTNodePath.Node
    %endif
    %assign isArraySel = (ASTParamNode.Op == "M_CANPRM_ID" || ...
                         (ASTParamNode.Op == "M_ID" && ...
                         ISFIELD(ASTParamNode, "ModelParameterIdx")))
  %endif
  %return isArraySel
%endfunction
   
%%Function:FcnGenExpr=======================================================
%%Abstract:
%%GivenarootASTNodeandtheotherarguments,thisfunction
%%recursivelytraversestheASTandgeneratesalanguageexpression
%%thatitreturns.
%%
%%Arguments:
%%pName-parameternamestring(mustbeavalididentifier)
%%accSysIdx-wheretheparameterisdeclared
%%parentSysIdx-systemwheretheparameterisbeingused.
%%ASTNode-RootnodeofASTwhichistobeconvertedtoan
%%expression
%%ParentNode-ParentnodeofASTnode(ASTNodeisTHEroot,passin
%%ASTNodeforParentNodealso)
%%ucv-SeedescriptioninLibBlockParameter
%%lcv-SeedescriptioninLibBlockParameter
%%sigIdx-SeedescriptioninLibBlockParameter
%%
%function FcnGenExpr(pName, accSysIdx, parentSysIdx, cs, ASTNode, ParentNode, ucv, lcv, sigIdx) void
  %%
  %assign retstr = ""
  %if (ASTNode.IsNonTerminal == 1)
    %% Param array selection
    %if FcnIsParamSel(ASTNode)
      %if ASTNode.ASTNode[2].IsNonTerminal == 0 && ...
        ASTNode.ASTNode[2].Op == "M_NUMBER"
        %assign sigIdx = CAST("Number", ASTNode.ASTNode[2].Value) - 1
        %assign ucvIndex = ""
      %else
        %assign sigIdx = 0
        %assign selExpr = ASTNode.ASTNode[2]
        %if selExpr.Op == "ExprList"
          %foreach i = selExpr.NumChildren
            %assign ind = "(%<FcnGenExpr(pName, accSysIdx, parentSysIdx, cs, selExpr.ASTNode[i], selExpr, "", "", 0)>)"
            %if i == 0
              %assign ucvIndex = ind
            %else
              %assign ucvIndex = ucvIndex + "*" + ind
            %endif
          %endforeach
        %else
          %assign ucvIndex = "%<FcnGenExpr(pName, accSysIdx, parentSysIdx, cs, ASTNode.ASTNode[2], ASTNode, "", "", 0)>"
        %endif
        %assign ucvIndex = "(int_T)(%<ucvIndex>) - 1"
      %endif
      %return FcnGenExpr(pName, accSysIdx, parentSysIdx, cs, ASTNode.ASTNode[0], ASTNode, ucvIndex, "", sigIdx)
    %elseif ASTNode.Op == "Dot"
        %% Find direct struct reference node
        %assign ASTNodePath = FcnGetDirectStructReferenceNode( ASTNode)
        %assert(ASTNodePath.path != "")
        %%
        %% Direct struct reference expression
        %%
        %assign retstr = "%<FcnGetDirectStructReferenceExpr(pName, accSysIdx, parentSysIdx, cs, ...
          ASTNodePath, ucv, lcv, sigIdx)>"
        %return (retstr)
    %else
      %% Vanilla Non-terminal
      %foreach i = ASTNode.NumChildren
        %assign this_node_str = ...
          "%<FcnGenExpr(pName, accSysIdx, parentSysIdx, cs, ASTNode.ASTNode[i], ASTNode, ucv, lcv, sigIdx)>"
        %if (this_node_str == "")
          %% Can only have a null string if caller requested imaginary part of a
          %% real expression/quantity. Since we currently do not support code
          %% generation for complex parameters in expressions, we can just
          %% jump out early and let the caller handle the situation as
          %% it wants.
          %return("")
        %endif
        %assign retstr = retstr + this_node_str
      %endforeach
      %if (ASTNode.Op == "UnaryPlus" || ...
        ASTNode.Op == "UnaryMinus" || ...
        ASTNode.Op == "Not")
        %return ("(%<retstr>)")
      %else
        %return (retstr)
      %endif
    %endif
  %else
    %% Terminal
    %assign retstr = ...
      "%<FcnConvertTerminalNodeToExpr(pName, accSysIdx, parentSysIdx, cs, ASTNode, ParentNode, ucv, lcv, sigIdx)>"
    %return (retstr)
  %endif
%endfunction %% FcnGenExpr
 
%%Function:SLibCanonicalParamCallSite========================================
%%Abstract:
%%Returnsthecanonicalparameterownerforasystemcallsite.
%%
%function SLibCanonicalParamCallSite(cs) void
  %if System[cs[0]].NumChildPrmArgs == 0
    %return SLibCanonicalParamCallSite(System[cs[0]].CallSites[cs[1]])
  %endif
  %return cs
%endfunction %% SLibCanonicalParamCallSite
 
%%Function:FcnConvertTerminalNodeToExpr======================================
%%Abstract:
%%GivenaterminalASTNode,generatesaC/Adalanguageexpressionand
%%returnit.
%%
%%Arguments:
%%pName-parameternamestring(mustbeavalididentifier)
%%accSysIdx-wheretheparameterisdeclared
%%parentSysIdx-systemwheretheparameterisbeingused.
%%ASTNode-Terminalnodethatistobeconvertedtoanexpression
%%ParentNode-Non-terminalparentofthisnode
%%ucv-SeedescriptioninLibBlockParameter
%%lcv-SeedescriptioninLibBlockParameter
%%sigIdx-SeedescriptioninLibBlockParameter
%%
%function FcnConvertTerminalNodeToExpr(pName, accSysIdx, parentSysIdx, cs, ...
  ASTNode, ParentNode, ucv, lcv, sigIdx) void
 
  %switch(ASTNode.Op)
    %case "M_CANPRM_ID"
      %assign prmCS = SLibCanonicalParamCallSite(cs)
      %if accSysIdx > prmCS[0]
        %assign sysCS = ::CompiledModel.System[cs[0]].CallSites[cs[1]]
        %assign ssBlk = ::CompiledModel.System[sysCS[2]].Block[sysCS[3]]
        %assign argIdx = ASTNode.CanonicalPrmArgDefIdx
        %assign childPrmIdx = ...
          ssBlk.CallSiteInfo.CanonicalPrmArg[argIdx].ChildPrmArgIdx
        %assign prm = SLibGetCallSitePrmArg(sysCS, childPrmIdx)
        %assign prmAST = prm.ASTNode
        %return ...
          FcnGenExpr(pName, accSysIdx, parentSysIdx, sysCS, prmAST, prmAST, ucv, lcv, sigIdx)
      %else
        %assign ident = SLibInvokeTLCInterface(SLibGetCurrentBlock(), ...
          "Param", 0, ASTNode.CanonicalPrmArgDefIdx, 0, "", "", "", "")
        %assign tlcIFv2Enabled = !ISEMPTY(ident)
        %assign canPrmArg = ...
          FcnGetCanParmArg(parentSysIdx, ASTNode.CanonicalPrmArgDefIdx)
        %assign cross = System[parentSysIdx].CrossNoArgFcnBound
        %assign tmpVect = SLibGetReimAndIdx(sigIdx)
        %assign reim = tmpVect[0]
        %assign idx = tmpVect[1]
        %assign width = LibBlockParameterWidth(canPrmArg)
        %assign indexer = SLibGet1DArrayIndexer(width, ucv, lcv, idx)
        %if !tlcIFv2Enabled
          %assign answer = LibGetRecordIdentifier(canPrmArg)
          %assign cross = System[accSysIdx].CrossNoArgFcnBound
          %assign ident = cross ? canPrmArg.GlobalIdentifier : answer
          %if canPrmArg.DeclareAsPointer == "yes"
            %assign ident = "(*%<ident>)"
          %endif
        %endif
        %if reim != "" && LibGetRecordIsComplex(canPrmArg)
          %return("%<ident>%<indexer>.%<reim>")
        %elseif reim == tImagPart && !LibGetRecordIsComplex(canPrmArg)
          %return ""
        %else
          %return("%<ident>%<indexer>")
        %endif
      %endif
      %break
       
    %case "M_ID"
      %% If this is an ID node with an Identifier like
      %% int8 or sqrt, we will want to return the mapping of the MATLAB
      %% function to the C function.
      %if (!ISFIELD(ASTNode, "ModelParameterIdx"))
        %return("%<FcnConvertIDToFcn(ASTNode)>")
      %endif
 
      %% Fall through since rest of computation is identical as for other
      %% parameter types
 
    %case "SL_INLINED"
    %case "SL_NOT_INLINED"
    %case "SL_CALCULATED"
      %assign mdlParam = ::CompiledModel.ModelParameters.Parameter[ASTNode.ModelParameterIdx]
       
      %assign answer = SLibModelParameter(pName, mdlParam, ucv, lcv, sigIdx)
 
      %return(answer)
      %%break
 
    %default
      %assign answer = FcnConvertOperatorNodeToExpr(ASTNode)
      %return(answer)
      %%break
 
  %endswitch
%endfunction %% FcnConvertTerminalNodeToExpr
 
%%Function:FcnGetDirectStructReferenceExpr======================================
%%Abstract:
%%Givenadirectstructreferencepath,generateslanguageexpression
%%
%%Arguments:
%%ASTNodePath-recordfromFcnGetDirectStructReferenceNode
%%otherparameterarethesameasforFcnConvertTerminalNodeToExpr
%%
%function FcnGetDirectStructReferenceExpr(pName, accSysIdx, parentSysIdx, cs, ASTNodePath, ...
  ucv, lcv, sigIdx) void
 
  %assign ASTNode = ASTNodePath.Node
  %assign memberStr = ASTNodePath.path
  %assign width = 1
   
  %if ASTNode.Op == "M_CANPRM_ID"
    %assign param = FcnGetCanParmArg(parentSysIdx, ASTNode.CanonicalPrmArgDefIdx)
  %else
    %assign param = ::CompiledModel.ModelParameters.Parameter[ASTNode.ModelParameterIdx]
  %endif
   
  %% For the main Parameter (which is set as tunable), it could have an
  %% array access index. This would be stored in the ASTNodePath. Extract
  %% that value now. If that value doesn't exist, then use sigIdx value that
  %% was passed into this function.
  %if( ISFIELD(ASTNodePath, "baseParamIndex"))
    %assign inputIdx = ASTNodePath.baseParamIndex
  %else
    %assign inputIdx = sigIdx
  %endif
 
  %assign retstr = ...
    FcnConvertTerminalNodeToExpr(pName, accSysIdx, parentSysIdx, cs, ASTNode, ASTNode, ...
    ucv, lcv, inputIdx)
   
  %% We need to get the width of the direct struct reference 'a.b.c'
  %% FcnConvertTerminalNodeToExpr checks the width of parameter 'a'
  %% which is different from the width of expression 'a.b.c'
   
  %% assign dtId to the original parameter's data type
  %% and overwrite it in loop for the elements in path
  %% dtId('a') --> dtId('a.b') --> dtId('a.b.c')
  %assign dtId = param.OriginalDataTypeIdx
   
  %assign szPath = SIZE(ASTNodePath.pathElem, 1)
  %foreach n = szPath
    %assert (LibIsStructDataType(dtId))
    %assign elemName = ASTNodePath.pathElem[n].name
    %assign idx = SLibFindDataTypeElementIdxByName(dtId, elemName)
    %assert (idx>=0)
    %assign width = LibDataTypeElementWidth(dtId, idx)
    %assign dtId = LibDataTypeElementDataTypeId(dtId, idx)
  %endforeach
   
  %assign memberIndexer = SLibGet1DStructFieldIndexer(width, memberStr, ucv, lcv, sigIdx)
  %assign retstr = retstr + "." + memberIndexer
   
  %return (retstr)
%endfunction %% FcnGetDirectStructReferenceExpr
   
%%Function:SLibFindDataTypeElementIdByName====================================
%%Return:elementidxor-1whennotfound
%%
%function SLibFindDataTypeElementIdxByName(id, name) void
  %assert (LibIsStructDataType(id))
  %foreach idx = LibDataTypeNumElements(id)
    %if name == LibDataTypeElementName(id, idx)
      %return idx
    %endif
  %endforeach
  %return -1
%endfunction %%LibFindDataTypeElementIdx
   
   
%%Function:LibPrepParameter==================================================
%%Abstract:
%%Collapsesingletondimensionsofparameters.
%%ConvertbooleanvaluestoTLC_TRUEorTLC_FALSE.
%%
%%paramAblockparameterrecordwithfieldsValueandDataTypeIdx
%%
%function LibPrepParameter(param) void
  %return SLibPrepParameterCore(param, TLC_FALSE)
%endfunction %% LibPrepParameter
 
 
%%Function:LibPrepParameterCore==============================================
%%Abstract:
%%HelperfunctionforLibPrepParameter.
%%Secondargumentcontrolsifenumsarereturnedasordinal/underlyingvalue.
%%
%%Seealso:LibPrepParameter
%%
%function SLibPrepParameterCore(param, ordinalValuesForEnums) void
  %assign prmValue = SLibGetValueFromParamRec(param, ordinalValuesForEnums)
  %if ISSLDATAREF(prmValue)
    %return prmValue
  %endif
  %assign nRows = SIZE(prmValue, 0)
  %assign nCols = SIZE(prmValue, 1)
  %%
  %assign prmClass = TYPE(prmValue)
  %if prmClass == "Vector"
    %if nCols == 1
      %assign prmVal = prmValue[0]
      %if LibGetDataTypeIdAliasedThruToFromId(LibGetRecordDataTypeId(param)) == tSS_BOOLEAN
        %assign prmVal = (prmVal == 1)
      %endif
    %else
      %assign prmVal = prmValue
      %if LibGetDataTypeIdAliasedThruToFromId(LibGetRecordDataTypeId(param)) == tSS_BOOLEAN
        %foreach idx = nCols
          %assign prmVal[idx] = (prmVal[idx] == 1)
        %endforeach
      %endif
    %endif
  %elseif prmClass == "Matrix"
    %if nRows == 1 && nCols == 1
      %assign prmVal = prmValue[0][0]
      %if LibGetDataTypeIdAliasedThruToFromId(LibGetRecordDataTypeId(param)) == tSS_BOOLEAN
        %assign prmVal = (prmVal == 1)
      %endif
    %elseif nRows == 1
      %assign prmVal = [0:%]
      %if LibGetDataTypeIdAliasedThruToFromId(LibGetRecordDataTypeId(param)) == tSS_BOOLEAN
        %foreach idx = nCols
          %assign prmVal[idx] = (prmValue[0][idx] == 1)
        %endforeach
      %else
        %foreach idx = nCols
          %assign prmVal[idx] = prmValue[0][idx]
        %endforeach
      %endif
    %elseif nCols == 1
      %assign prmVal = [0:%]
      %if LibGetDataTypeIdAliasedThruToFromId(LibGetRecordDataTypeId(param)) == tSS_BOOLEAN
        %foreach idx = nRows
          %assign prmVal[idx] = (prmValue[idx][0] == 1)
        %endforeach
      %else
        %foreach idx = nRows
          %assign prmVal[idx] = prmValue[idx][0]
        %endforeach
      %endif
    %else
      %assign prmVal = prmValue
      %if LibGetDataTypeIdAliasedThruToFromId(LibGetRecordDataTypeId(param)) == tSS_BOOLEAN
        %foreach rowIdx = nRows
          %foreach colIdx = nCols
            %assign prmVal[rowIdx][colIdx] = (prmVal[rowIdx][colIdx] == 1)
          %endforeach
        %endforeach
      %endif
    %endif
  %else
    %if LibGetDataTypeIdAliasedThruToFromId(LibGetRecordDataTypeId(param)) == tSS_BOOLEAN
      %assign prmVal = (prmValue == 1)
    %else
      %assign prmVal = prmValue
    %endif
  %endif
  %%
  %%
  %return prmVal
%endfunction %% LibPrepParameterCore
   
 
%%Function:SLibModelParameter================================================
%%Abstract:
%%Givenamodelparameter,generateaC/Adaexpressionstringtoaccess
%%thedesiredelement(asindicatedbyucv,lcv,andsigIdx).
%%
%%Arguments:
%%pName-parameternamestring(mustbeavalididentifier)
%%mdlParam-ParameterrecordfromModelParameterstable
%%ucv-SeedescriptioninLibBlockParameter
%%lcv-SeedescriptioninLibBlockParameter
%%sigIdx-SeedescriptioninLibBlockParameter
%%
%function SLibModelParameter(pName, mdlParam, ucv, lcv, sigIdx)
  %assign tmpVect = SLibGetReimAndIdx(sigIdx)
  %assign reim = tmpVect[0]
  %assign idx = tmpVect[1]
   
  %% The imaginary part of a non-complex parameter is always NULL
  %if reim == tImagPart && !LibGetRecordIsComplex(mdlParam)
    %% Note: SLibModelParameter always returns the empty string if the caller
    %% requested the imaginary part of a non-complex parameter. However,
    %% if calling the context of an expression, the caller might prefer to use
    %% '0' instead.
    %return ""
  %endif
   
  %if ucv != ""
    %assign idx = 0
  %endif
   
  %assign prmSize = SLibGetSizeOfValueFromParamRec(mdlParam)
  %assign nCols = prmSize[1]
  %assign sigIndexer = SLibGet1DArrayIndexer(nCols, ucv, lcv, idx)
   
  %% Check for floating-point types if integer only code
  %if PurelyIntegerCode
    %assign dTypeId = LibGetRecordDataTypeId(mdlParam)
    %if LibIsBuiltInOrCustomFloatDatatype(dTypeId)
      %<SLibCacheIntegerOnlyWarning(LibGetRecordIdentifier(mdlParam),"ModelParameter")>
    %endif
  %endif
 
  %if (ucv != "") && (nCols > 1)
    %if LibHasCustomStorage(mdlParam)
      %return LibCustomData(mdlParam,"contents",sigIndexer,reim)
    %elseif mdlParam.UseAccessFunctions
      %return FcnGetAccessFunctionSignalReference(mdlParam, TLC_FALSE, sigIndexer)
    %endif
    %assign answer = FcnGenerateNonEmptyUcvParameter(mdlParam, sigIndexer, reim)
  %elseif InlineParameters != 0 && !LibIsDataTypeMultiWordFixpt(mdlParam.OriginalDataTypeIdx)
    %% FcnGenerateInlinedParameter handles both the InlineParameters ON case for all tarets
    %% and the InlineParameter case for code generation targets
    %assign answer = FcnGenerateInlinedParameter(pName, mdlParam, ...
      sigIndexer, lcv, idx, reim)
  %else
    %% FcnGenerateNonInlinedParameter handles the InlineParameter OFF case
    %% for simulation targets
    %assign answer = FcnGenerateNonInlinedParameter(pName, mdlParam, ...
      sigIndexer, lcv, reim)
  %endif
  %return(answer)
%endfunction %% SLibModelParameter
 
 
%%Function:LibModelParameterAddr=============================================
%%Abstract:
%%Givenamodelparameterrecord(mdlParam)fromtheModelParameters
%%table,ucv,lcv,andsigIdx,returntheC/Adaexpressiontoaccess
%%theaddressoftheparameterinanexpression.
%%
%function LibModelParameterAddr(mdlParam, ucv, lcv, sigIdx)
  %assign tmpVect = SLibGetReimAndIdx(sigIdx)
  %assign reim = tmpVect[0]
  %assign idx = tmpVect[1]
 
  %% Check for floating-point types if integer only code
  %if PurelyIntegerCode
    %assign dTypeId = LibGetRecordDataTypeId(mdlParam)
    %if LibIsBuiltInOrCustomFloatDatatype(dTypeId)
      %<SLibCacheIntegerOnlyWarning(LibGetRecordIdentifier(mdlParam),"ModelParameter")>
    %endif
  %endif
 
  %assign storageClass = mdlParam.StorageClass
 
  %if ucv != ""
    %assign idx = 0
  %endif
   
  %assign prmSize = SLibGetSizeOfValueFromParamRec(mdlParam)
  %assign nCols = prmSize[1]
  %assign sigIndexer = SLibGet1DArrayIndexer(nCols, ucv, lcv, idx)
  %if storageClass == "Custom"
    %if !LibCustomDataIsAddressable(mdlParam)
      %<SLibReportErrorWithIdAndArgs("RTW:tlc:CSCParamNotAddressable", "%<LibGetRecordVarName(mdlParam)>")>
    %endif
    %return LibCustomData(mdlParam,"address",sigIndexer,reim)
  %elseif mdlParam.UseAccessFunctions
    %return FcnGetAccessFunctionSignalReference(mdlParam, TLC_TRUE, sigIndexer)
  %else
    %return "%<FcnAccessModelParameterRef(mdlParam, sigIndexer)>"
  %endif
%endfunction %% LibModelParameterAddr
 
 
%%Function:FcnConvertIDToFcn================================================
%%Abstract:
%%ConvertthegivenASTNodestringidentifiertoaC/Adafunctionname
%%Forfunctionnames,theTFLisqueriedforanimplementationname.
%%IfanentryexistsintheTFL,theimplementationnameisreturned
%%andasasideeffect,theheaderfileisaddedtomodel.hviathe
%%TFLheadermanagementmechanism.
%%Example:
%%FcnConvertIDToFcn(AstNode)
%%returns"sqrt"ifastNode.Identifier="sqrt"
%%returns"(int8_T)"ifastNode.Identifier="int8"
%%
%function FcnConvertIDToFcn(astNode)
  %assign numInputs = 1
  %switch(astNode.Identifier)
    %case ("int8")
      %return ("(int8_T)")
 
    %case ("int16")
      %return ("(int16_T)")
 
    %case ("int32")
      %return ("(int32_T)")
 
    %case ("uint8")
      %return ("(uint8_T)")
 
    %case ("uint16")
      %return ("(uint16_T)")
 
    %case ("uint32")
      %return ("(uint32_T)")
 
    %case ("single")
      %return ("(real32_T)")
 
    %case ("double")
      %return ("(real_T)")
       
    %case ("boolean")
      %return ("(boolean_T)")
 
    %case ("sin")
      %assign fcnName = "sin"
      %break
 
    %case ("cos")
      %assign fcnName = "cos"
      %break
 
    %case ("tan")
      %assign fcnName = "tan"
      %break
 
    %case ("asin")
      %assign fcnName = "asin"
      %break
 
    %case ("acos")
      %assign fcnName = "acos"
      %break
 
    %case ("atan")
      %assign fcnName = "atan"
      %break
 
    %case ("atan2")
      %assign fcnName = "atan2"
      %assign numInputs = 2
      %break
 
    %case ("sinh")
      %assign fcnName = "sinh"
      %break
 
    %case ("cosh")
      %assign fcnName = "cosh"
      %break
 
    %case ("tanh")
      %assign fcnName = "tanh"
      %break
 
    %case ("sqrt")
      %assign fcnName = "sqrt"
      %break
 
    %case ("exp")
      %assign fcnName = "exp"
      %break
 
    %case ("log")
      %assign fcnName = "log"
      %break
 
    %case ("log10")
      %assign fcnName = "log10"
      %break
 
    %case ("abs")
      %assign fcnName = "abs"
      %break
 
    %case ("floor")
      %assign fcnName = "floor"
      %break
 
    %case ("ceil")
      %assign fcnName = "ceil"
      %break
 
    %case ("sign")
      %assign fcnName = "sign"
      %break
 
    %case ("half")
      %return ("(real16_T)")
 
    %default
      %return (astNode.Identifier)
 
  %endswitch
  %assign implName = ""
  %assign dataType = SLibGetASTNodeDataTypeId(astNode)
  %if numInputs == 1
    %assign implName = SLibGetMathFcnNameFromTFL( fcnName, dataType, dataType, "")
  %elseif numInputs == 2
    %assign implName = SLibGetMathFcnNameFromTFL( fcnName, dataType, dataType, dataType)
  %endif
  %if implName == ""
      %assign errTxt = "The function key name, '%<fcnName>', does not exist in the selected "...
        "Target Function Library."
      %<LibBlockReportError([], errTxt)>
  %endif
  %return (implName)
%endfunction %% FcnConvertIDToFcn
 
 
%%Function:FcnGenerateNonEmptyUcvParameter==================================
%%Abstract:
%%Returnsappropriatecodeforamodelparameterwiththeassumptionthat
%%ucv!="".
%%
%%sigIndexeristheresultofacalltoSLibGet1DArrayIndexere.g.
%%
%%%assignsigIndexer=SLibGet1DArrayIndexer(nCols,ucv,lcv,idx)
%%
%%Arguments:
%%mdlParam-ParameterfromModelParametersrecord
%%sigIndexer-GeneratedbySLibGet1DArrayIndexer
%%reim-%<tRealPart>or%<tImagPart>or""
%%
%function FcnGenerateNonEmptyUcvParameter(mdlParam, sigIndexer, reim)
  %assign answer = FcnAccessModelParameter(mdlParam, sigIndexer)
  %if reim != "" && LibGetRecordIsComplex(mdlParam)
    %assign answer = answer + ".%<reim>"
  %endif
  %return (answer)
%endfunction %% FcnGenerateNonEmptyUcvParameter
 
 
%%Function:FcnGenerateInlinedParameter======================================
%%Abstract:
%%Generatecodeforaparameterassuminginlineparametersison.
%%Returnsappropriatecodeforamodelparameterwiththeassumptionthat
%%inlineparametersareon.
%%
%%sigIndexeristheresultofacalltoSLibGet1DArrayIndexere.g.
%%
%%%assignsigIndexer=SLibGet1DArrayIndexer(nCols,ucv,lcv,idx)
%%
%%Arguments:
%%pName-parameternamestring(mustbeavalididentifier)
%%mdlParam-ParameterfromModelParametersrecord
%%sigIndexer-GeneratedbySLibGet1DArrayIndexer
%%lcv-SeedescriptioninLibBlockParameter
%%idx-SeedescriptioninLibBlockParameter
%%reim-%<tRealPart>or%<tImagPart>or""
%%
%function FcnGenerateInlinedParameter(pName, mdlParam, sigIndexer, ...
  lcv, idx, reim)
  %assign storageClass = mdlParam.StorageClass
  %assign prmSize = SLibGetSizeOfValueFromParamRec(mdlParam)
  %assign nCols = prmSize[1]
 
  %if (lcv != "" && nCols > 1)
    %% Parameter is a vector and it's being rolled. Use the local variable
    %% name that rolllib uses for the parameter.
    %% The parameter must exist in memory if not generating dead code
 
    %if mdlParam.Tunable == "yes"
      %assign varName = "p_%<LibGetRecordIdentifier(mdlParam)>"
    %else
      %assign varName = "p_%<pName>"
    %endif
    %assign answer = "%<varName>%<sigIndexer>"
  %elseif reim == "" && LibGetRecordIsComplex(mdlParam)
    %% The parameter is complex and it's being accessed as a structure
    %% (i.e., not accessing the real or the imaginary part directly).
    %% The parameter must exist in memory if not generating dead code.
 
    %if storageClass == "Auto"
      %assert !mdlParam.UseAccessFunctions
    %elseif storageClass == "Custom" || SLibIsLegacyStorageClassForDataRecord(mdlParam)
      %% Note: ucv is null if we are in this function
      %return LibCustomData(mdlParam,"contents",sigIndexer,reim)
    %elseif storageClass == "ImportedExtern" || ...
      storageClass == "ImportedExternPointer"
      %% Disallow imported complex parameters (for now)
      %assign errTxt = "Imported complex parameters not supported. " ...
        "This occurred in parameter %<LibGetRecordIdentifier(mdlParam)>."
      %<LibBlockReportError([], errTxt)>
    %endif
    %assign answer = FcnAccessModelParameter(mdlParam, sigIndexer)
     
  %elseif (mdlParam.Tunable == "yes")
    %% Normally we would inline the parameter value, however, this is a
    %% tunable parameter. Therefore, interface the parameter by name
    %% instead of by value.
    %if storageClass == "Custom" || SLibIsLegacyStorageClassForDataRecord(mdlParam)
      %% Note: ucv is null if we are in this function
      %return LibCustomData(mdlParam,"contents",sigIndexer,reim)
    %elseif mdlParam.UseAccessFunctions
      %return FcnGetAccessFunctionSignalReference(mdlParam, TLC_FALSE, sigIndexer)
    %endif
    %assign answer = FcnAccessModelParameter(mdlParam, sigIndexer)
     
  %else
    %% Return the actual value of parameter, scalar expanding on the input
    %% index if necessary.
    %assign pIdx = (nCols > 1) ? idx : 0
    %assign complex = LibGetRecordIsComplex(mdlParam)
   
    %return SLibGenModelConstPrmMacroAccess(mdlParam, sigIndexer, [%<pIdx>], complex, reim, ...
      "Vector")
  %endif
 
  %if reim != "" && LibGetRecordIsComplex(mdlParam)
    %assign answer = answer + ".%<reim>"
  %endif
 
  %return(answer)
%endfunction %% FcnGenerateInlinedParameter
 
 
%%Function:FcnGenerateNonInlinedParameter====================================
%%Abstract:
%%Generatecodeforaparameterassuminginlineparametersisoff
%%Returnsappropriatecodeforamodelparameterwiththeassumptionthat
%%inlineparametersareoff.
%%
%%sigIndexeristheresultofacalltoSLibGet1DArrayIndexere.g.
%%
%%%assignsigIndexer=SLibGet1DArrayIndexer(nCols,ucv,lcv,idx)
%%
%%Arguments:
%%pName-parameternamestring(mustbeavalididentifier)
%%mdlParam-ParameterfromModelParametersrecord
%%sigIndexer-GeneratedbySLibGet1DArrayIndexer
%%lcv-SeedescriptioninLibBlockParameter
%%reim-%<tRealPart>or%<tImagPart>or""
%%
%function FcnGenerateNonInlinedParameter(pName, mdlParam, sigIndexer, lcv, reim)
  %% Don't have to check storage class of mdlParam since inline parameters is
  %% assumed to be off ==> storage class is Auto
     
  %assign prmSize = SLibGetSizeOfValueFromParamRec(mdlParam)
  %assign nCols = prmSize[1]
  %if lcv != "" && nCols > 1
    %% rolling
    %if mdlParam.Tunable == "yes"
      %assign varName = "p_%<LibGetRecordIdentifier(mdlParam)>"
    %else
      %assign varName = "p_%<pName>"
    %endif
    %assign answer = "%<varName>%<sigIndexer>"
  %else
    %% not rolling
    %assign answer = FcnAccessModelParameter(mdlParam, sigIndexer)
  %endif
  %if reim != "" && LibGetRecordIsComplex(mdlParam)
    %assign answer = answer + ".%<reim>"
  %endif
  %return (answer)
%endfunction %% FcnGenerateNonInlinedParameter
 
 
%%Function:FcnConvertOperatorNodeToExpr======================================
%%Abstract:
%%GivenaterminalASTNodethatisanoperator,generatesaC/Ada
%%languageexpression.
%%
%%An"operator"meansthatthenodeisnotanM_ID,SL_INLINED,
%%SL_NOT_INLINED,orSL_CALCULATED.
%%
%%Arguments:
%%ASTNode-Terminalnodethatistobeconvertedtoanexpression
%%Assumedtobean"operator"(seeDescription)
%%
%%
%function FcnConvertOperatorNodeToExpr(ASTNode)
  %switch(ASTNode.Op)
    %case "M_NUMBER"
    %case "M_HEX_NUMBER"
    %case "M_BIN_NUMBER"
      %return(%<ASTNode.Value>)
      %%break
 
    %case "M_STRING"
      %return(%<ASTNode.Value>)
      %%break
       
    %case "M_MUL"
    %case "M_DOTMUL"
      %return " * "
      %%break
 
    %case "M_DIV"
    %case "M_DOTDIV"
      %return " / "
      %%break
 
    %case "M_ADD"
      %% Don't have any spaces around '+'; This takes care of Unary cases also.
      %% Else you have to look at ParentNode and determine output based on its
      %% value.
      %return "+"
      %%break
 
    %case "M_SUB"
      %% See comment for M_ADD
      %% Might still need to consider unary minus for Ada but this would have
      %% to be at non-terminal node level.
      %return "-"
      %%break
 
    %case "M_LT"
      %return " < "
      %%break
 
    %case "M_LTEQ"
      %return " <= "
      %%break
 
    %case "M_GT"
      %return " > "
      %%break
 
    %case "M_GTEQ"
      %return " >= "
      %%break
 
    %case "M_EQEQ"
      %return " == "
      %%break
 
    %case "M_NOTEQ"
      %return " != "
      %%break
 
    %case "M_AND"
      %return " && "
      %%break
 
    %case "M_OR"
      %return " || "
      %%break
 
    %case "M_NOT"
      %return " !"
      %%break
 
    %case "M_LRB"
      %return "( "
      %%break
 
    %case "M_RRB"
      %return " )"
      %%break
 
    %case "M_DOT"
      %% Don't have any spaces around '.'; This takes care of structure parameters.
      %return "."
      %%break
 
    %default
      %assign errTxt = "Unrecognized Identifier: %<ASTNode.Op>"
      %<LibBlockReportFatalError([], errTxt)>
      %return " "
      %%break
  %endswitch
%endfunction %% FcnConvertOperatorNodeToExpr
 
%%FunctionFcnBlockParameterIndex===================================
%%Abstract:
%%Returntheparameterindexandmemberstringofablockparameter.
%%
%function FcnBlockParameterIdxMemberStr(param) void
  %assign memberStr = ""
  %if ISFIELD(param, "ASTNode")
    %assign ASTNode = param.ASTNode
    %switch (ASTNode.Op)
      %case "SL_INLINED"
      %case "SL_NOT_INLINED"
      %case "SL_CALCULATED"
        %assign paramIdx = [%<ASTNode.ModelParameterIdx>, 0]
        %% not a canonical parameter
        %createrecord record {param paramIdx; member memberStr}
        %return record
      %default
        %% In this case, slightly more complicated
        %% First, ensure that only terminal node in the entire AST
        %% is a single M_ID
        %% If it is not, error out.
        %assign paramIdx = FcnGetUniqueNode(ASTNode)
        %if (paramIdx[0] == -1)
          %assign ASTVarPath = FcnGetDirectStructReferenceNode(ASTNode)
          %if (ASTVarPath.path != "")
            %assign memberStr = ASTVarPath.path
            %assign paramIdx = FcnGetUniqueNode(ASTVarPath.Node)
            %assert(paramIdx[0] != -1)
          %endif
        %endif
        %% Assert: (ASTNode.Value == prmValue)
        %if (paramIdx[0] != -1) || !ISFIELD(ASTVarPath, "baseParamIndex")
            %createrecord record {param paramIdx; member memberStr}
            %return record
        %else
             %createrecord record {param paramIdx; member memberStr baseParamIndex ASTVarPath.baseParamIndex}
             %return record
        %endif
    %endswitch
  %else
    %assign paramIdx = [%<param.MdlPrmIdx>, 0]
    %if param.ArgDefIdx >= 0
      %assign paramIdx = [%<param.ArgDefIdx>, 1]
    %endif
    %createrecord record {param paramIdx; member memberStr}
    %return record
  %endif
%endfunction %% FcnBlockParameterIndex
 
%%FcnBlockParameterAddr=======================================================
%%Abstract:
%%WorkhorsefunctionforLibBlockParameterAddr.Returnstheaddressofa
%%blockparameter.
%%
%function FcnBlockParameterAddr(param, ucv, lcv, idx, simpleForm, constOutputExpr) void
 
  %assign prmSize = SLibGetSizeOfValueFromParamRec(param)
  %assign nRows = prmSize[0]
  %assign nCols = prmSize[1]
  %assign memberStr = ""
 
  %if nRows > 1
    %assign errTxt = "Number of rows greater than 1. Must " ...
      "access parameter %<param.Name> using LibBlockMatrixParameterAddr."
    %<LibBlockReportError([], errTxt)>
  %endif
 
  %if ucv != ""
    %% idx is ignored when ucv is non-null
    %assign idx = 0
  %endif
   
  %assign sigIndexer = SLibGet1DArrayIndexer(nCols, ucv, lcv, idx)
  %assign useIndex = TLC_TRUE
  %if CanUseSimpleReferenceFormat(param, sigIndexer)
    %assign useIndex = TLC_FALSE
  %endif
   
  %assign record = FcnBlockParameterIdxMemberStr(param)
  %assert(ISFIELD(record, "param"))
  %assert(ISFIELD(record, "member"))
  %assign paramIdx = record.param
  %assign memberStr = record.member
 
  %if (paramIdx[0] == -1)
 
    %if constOutputExpr
      %openfile errTxt
This block is connected to a block that is attempting to take the address
of its parameter "%<param.Name>", yet this is not possible because an
operation converted the parameter to the tunable expression
"%<param.String>". One workaround is to testpoint the signal leaving
this block. Another workaround is to place a Signal Conversion block
at the output of this block, and select its parameter "Exclude this
block from 'Block reduction' optimization".
      %closefile errTxt
    %else
      %openfile errTxt
This block is unable to get the address of its parameter "%<param.Name>"
because an operation converted the parameter to the non-trivial tunable
expression "%<param.String>". Blocks that require a parameter address
support direct use of tunable parameters. However, when an operation
such as a data type conversion or math operation is applied, a
non-trivial expression that cannot be accessed by address can result.
For more information, including limitations and workarounds, see
sections in the Simulink Coder documentation on tunable
expressions and data type considerations for tunable workspace parameters.
      %closefile errTxt
    %endif
    %assign errTxt = FEVAL("strrep",errTxt,"/n","")
    %<LibBlockReportError([], errTxt)>
  %endif
 
  %if paramIdx[1] %% Is canonical parameter ?
    %assign bAddr = (memberStr != "")
    %assign ident = SLibInvokeTLCInterface(SLibGetCurrentBlock(), ...
      "Param", 0, paramIdx[0], bAddr, "", "", "", "")
    %assign tlcIFv2Enabled = !ISEMPTY(ident)
    %if !tlcIFv2Enabled
      %assign canPrmArg = FcnGetCanParmArg(BlockIdx[0], paramIdx[0])
      %assign cross = System[BlockIdx[0]].CrossNoArgFcnBound
      %assign ident = cross ? canPrmArg.GlobalIdentifier : LibGetRecordIdentifier(canPrmArg)
    %endif
    %if (memberStr != "")
      %% Direct struct reference. Struct argument is passed by pointer
      %if useIndex
        %return "&(%<ident>->%<memberStr>%<sigIndexer>)"
      %else
        %return "%<ident>->%<memberStr>"
      %endif
    %endif
    %if useIndex
      %return "&%<ident>%<sigIndexer>"
    %else
      %return ident
    %endif
  %endif
   
  %assign mdlParam = ::CompiledModel.ModelParameters.Parameter[paramIdx[0]]
  %assign storageClass = mdlParam.StorageClass
     
  %% Check for floating-point types if integer only code
  %if PurelyIntegerCode
    %assign dTypeId = LibGetRecordDataTypeId(mdlParam)
    %if LibIsBuiltInOrCustomFloatDatatype(dTypeId)
      %<SLibCacheIntegerOnlyWarning(Name,"Parameter")>
    %endif
  %endif
   
  %if (storageClass == "ImportedExternPointer") && (nCols == 1)
    %if (memberStr != "")
      %% Direct struct reference. Struct argument is passed by pointer
      %assign ident = LibGetRecordIdentifier(mdlParam)
      %return "&(%<ident>->%<memberStr>)"
    %endif
    %return LibGetRecordIdentifier(mdlParam)
  %elseif storageClass == "Custom"
    %if !LibCustomDataIsAddressable(mdlParam)
      %<SLibReportErrorWithIdAndArgs("RTW:tlc:CSCParamNotAddressable", "%<LibGetRecordVarName(mdlParam)>")>
    %endif
     
    %if !ISEMPTY(memberStr)
      %assert(ISEMPTY(sigIndexer))
      %assign sigIndexer = "%<FcnGetStructFieldAccesser(mdlParam, memberStr)>"
    %endif
       
    %return LibCustomData(mdlParam,"address",sigIndexer,"")
  %else
    %if mdlParam.UseAccessFunctions
      %return FcnGetAccessFunctionSignalReference(mdlParam, TLC_TRUE, sigIndexer)
    %elseif (memberStr != "")
      %% Direct struct reference.
      %return "%<FcnAccessStructModelParameterRef(mdlParam, param, memberStr, sigIndexer)>"
    %endif
    %if simpleForm && storageClass != "Auto_SFCN"
      %assign sigIndexer = ""
      %assign prmStr = FcnAccessModelParameter(mdlParam, sigIndexer)
    %else
      %assign prmStr = FcnAccessModelParameterRef(mdlParam, sigIndexer)
    %endif
    %assign cast = ""
    %if SLibGenConstRTPForPrm(mdlParam) && SLibGetGlobalConstantMemorySectionHasVolatile()
      %assign dtypeName = LibGetRecordCompositeDataTypeName(mdlParam)
      %assign cast = "(const %<dtypeName>*)"
    %endif
    %return cast + prmStr
  %endif
 
%endfunction %% FcnBlockParameterAddr
 
 
%%DocFunction{ParameterFunctions}:LibBlockParameterAddr=====================
%%Abstract:
%%Returnstheaddressofablockparameter.
%%
%%UsingLibBlockParameterAddrtoaccessaparameterwhentheglobal
%%InlineParametersvariableisequaltoonewillcausethevariable
%%tobedeclared"const"inRAMinsteadofbeinginlined.
%%
%%Also,tryingtoaccesstheaddressofanexpressionwheninline
%%parametersisonandtheexpressionhasmultipletunable/rolled
%%variablesinit,willresultinanerror.
%%
%function LibBlockParameterAddr(param, ucv, lcv, idx) void
 
  %% See Also:
  %% LibBlockParameter, LibBlockInputSignalAddr, LibBlockOutputSignalAddr,
  %% LibBlockParameterBaseAddr
  %%
   
  %return FcnBlockParameterAddr(param, ucv, lcv, idx, 0, TLC_FALSE)
   
%endfunction %% LibBlockParameterAddr
 
 
%%SLibBlockParameterAddrAsOutputExpr========
%%Abstract:
%%Returnstheaddressofablockparameterasablockoutputexpression
%%
%%WewouldexpectthisfunctiontobecalledonlyfromaTLCblock's
%%BlockOutputSignal()function(forexpressionfolding)
%%
%%UsingSLibBlockParameterAddrAsOutputExprtoaccessaparameterwhenthe
%%globalInlineParametersvariableisequaltoonewillcausethe
%%variabletobedeclared"const"inRAMinsteadofbeinginlined.
%%
%%Also,tryingtoaccesstheaddressofanexpressionwheninline
%%parametersisonandtheexpressionhasmultipletunable/rolled
%%variablesinit,willresultinanerror.
%%
%function SLibBlockParameterAddrAsOutputExpr(param, ucv, lcv, idx) void
 
  %return FcnBlockParameterAddr(param, ucv, lcv, idx, 0, TLC_TRUE)
   
%endfunction %% LibBlockParameterAddr
 
 
%%FcnBlockParameterBaseAddr=================
%%Abstract:
%%Helperfunctionforreturningthebaseaddressofablockparameter.
%%
%function FcnBlockParameterBaseAddr(param, constOutputExpr) void
 
  %if LibGetRecordIsStdContainer(param)
    %assign simpleForm = 0
  %elseif SLibGetWidthOfValueFromParamRec(param) > 1
    %% vectors and matrices can drop the "&" and "[0]"
    %assign simpleForm = 1
  %else
    %% scalars do not drop the "&"
    %assign simpleForm = 0
  %endif
 
  %return FcnBlockParameterAddr(param,"","",0,simpleForm, constOutputExpr)
   
%endfunction %% FcnBlockParameterBaseAddr
 
 
%%DocFunction{ParameterFunctions}:LibBlockParameterBaseAddr=================
%%Abstract:
%%Returnsthebaseaddressofablockparameter.
%%
%%UsingLibBlockParameterBaseAddrtoaccessaparameterwhentheglobal
%%InlineParametersvariableisequaltoonewillcausethevariable
%%tobedeclared"const"inRAMinsteadofbeinginlined.
%%
%%Also,tryingtoaccesstheaddressofanexpressionwheninline
%%parametersisonandtheexpressionhasmultipletunable/rolled
%%variablesinit,willresultinanerror.
%%
%function LibBlockParameterBaseAddr(param) void
 
  %% See Also:
  %% LibBlockParameter, LibBlockInputSignalAddr, LibBlockOutputSignalAddr,
  %% LibBlockParameterAddr
  %%
   
  %return FcnBlockParameterBaseAddr(param, TLC_FALSE)
   
%endfunction %% LibBlockParameterAddr
 
 
%%SLibBlockParameterBaseAddrAsOutputExpr=================
%%Abstract:
%%Returnsthebaseaddressofablockparameterasanoutputexpression
%%
%%UsingSLibBlockParameterBaseAddrAsOutputExprtoaccessaparameter
%%whentheglobalInlineParametersvariableisequaltoonewillcause
%%thevariabletobedeclared"const"inRAMinsteadofbeinginlined.
%%
%%Also,tryingtoaccesstheaddressofanexpressionwheninline
%%parametersisonandtheexpressionhasmultipletunable/rolled
%%variablesinit,willresultinanerror.
%%
%function SLibBlockParameterBaseAddrAsOutputExpr(param) void
 
  %return FcnBlockParameterBaseAddr(param, TLC_TRUE)
 
%endfunction %% SLibBlockParameterAddrAsOutputExpr
 
 
%%DocFunction{ParameterFunctions}:LibBlockParameterValue====================
%%Abstract:
%%Determinethenumericvalueofaparameter.
%%
%%Ifyouareonlyaccessingtheparametervalue(s)usingthisfunction,you
%%shouldconsiderconvertingtheparametertoaParamSetting.Thiswill
%%producemoreefficientcodesincetheparameterwouldnotbedeclaredasa
%%variableinthecode.
%%
%%Ifyouareonlyaccessingtheparametervalue(s)using
%%LibBlockParameterValueorLibBlockParameterString,youshouldconsider
%%convertingtheparametertoaParamSetting.Thiswillproducemore
%%efficientcodesincetheparameterwouldnotbedeclaredasavariablein
%%thecode.
%%
%%Example:
%%Ifyouwanttogeneratecodeforadifferentintegratordepending
%%onablock'sparameter,youcouldusethefollowing:
%%
%%%assignmode=LibBlockParameterValue(Integrator,0)
%%%switch(mode)
%%%case1
%%%<CodeForIntegrator1>
%%%break
%%%case2
%%%<CodeForIntegrator2>
%%%break
%%%default
%%Error:Unrecognizedintegratorvalue.
%%%break
%%%endswitch
%%
%function LibBlockParameterValue(param, elIdx) void
 
  %% See Also:
  %% LibBlockParameter
  %%
  %if FixPt_IsParameterDataSizeLargerThan32(param)
    %error Simulink Coder Fatal Error: LibBlockParameterValue: param's data type size should be 32 or less
  %endif
  %% Split the overloaded idx
   
  %assign idNum = SLibGetReimAndIdx(elIdx)
  %assign reim = idNum[0]
  %assign idx = idNum[1]
  %assign complex = LibGetRecordIsComplex(param)
  %assign prmSize = SLibGetSizeOfValueFromParamRec(param)
  %assign nCols = prmSize[1]
  %% Scalar expand the parameter if necessary
  %% If complex, must ask specifically for real or imaginary part
  %assign pIdx = (nCols > 1) ? idx : 0
 
  %return FcnGetVectPrmValueCore(param, "", pIdx, complex, reim, 1)
   
%endfunction %% LibBlockParameterValue
 
 
%function FcnGetNonBuiltInRe(prmStrVal) void
  %% multiword complex 1+2i is in the format of " {0x1UL, 0x0UL} + {0x2UL, 0x0UL} i"
  %assign complexStr = prmStrVal
  %assign re = FEVAL("regexprep", complexStr, "([^/+]+).*", "$1")
  %return re
%endfunction
 
 
%function FcnGetNonBuiltInIm(prmStrVal) void
  %% multiword complex 1+2i is in the format of " {0x1UL, 0x0UL} + {0x2UL, 0x0UL} i "
  %assign complexStr = prmStrVal
  %assign hasIm = !ISEMPTY(FEVAL("regexp",complexStr,"i"))
  %if hasIm
    %assign im = FEVAL("regexprep", complexStr, "[^/+]/+.([^/+]+)i", "$1")
  %else
    %assign im = "0"
  %endif
   
  %return im
%endfunction
 
 
%%Function:FcnGetVectPrmValueCore=============================================
%%Abstract:
%%Gettheindexedvalueofthespecifiedvectormodelparameter
%%
%function FcnGetVectPrmValueCore(param, sigIndexer, pIdx, complex, reim, needRawValue) void
  %if complex
    %if reim != tRealPart && reim != tImagPart
      %assign errTxt = "The parameter %<param.Name> is complex. Hence, " ...
        "the caller should specify whether the real part or the imaginary " ...
        "part is to be returned."
      %<LibBlockReportError([],errTxt)>
    %endif
  %elseif reim == tImagPart
    %% imaginary part of a non-complex parameter is NULL
    %return ""
  %endif
   
  %% Determine true size
  %assign prmValue = SLibGetValueFromParamRec(param, TLC_TRUE)
  %assign nRows = SIZE(prmValue, 0)
  %assign value = prmValue
 
  %% treat 1 x n matrix as vector
  %if TYPE(prmValue) == "Matrix"
    %if nRows > 1
      %assign errTxt = "Must access the parameter %<param.Name> via "...
        "LibBlockMatrixParameterValue."
      %<LibBlockReportError([], errTxt)>
    %endif
    %assign value = prmValue[0]
  %endif
   
  %% Check for floating-point types if integer only code
  %assign dTypeId = LibGetRecordDataTypeId(param)
  %if PurelyIntegerCode && LibIsBuiltInOrCustomFloatDatatype(dTypeId)
    %<SLibCacheIntegerOnlyWarning(Name,"Parameter")>
  %endif
   
  %if LibIsEnumDataType(dTypeId)
    %% Return enum string instead of ordinal number (cannot be complex).
    %assign theVal = SLibGetEnumTypeCodeGenStringFromIndex(dTypeId, REAL(value[pIdx]))
     
  %elseif (LibIsBuiltInDataType(LibGetDataTypeStorageIdFromId(dTypeId)) || ...
          LibIsHalfDataType(dTypeId))
    %% Get the value
    %if complex
      %if reim == tRealPart
        %assign pValue = REAL(value[pIdx])
      %elseif reim == tImagPart
        %assign pValue = IMAG(value[pIdx])
      %else
        %assign errTxt = "Invalid input argument (%<elIdx>). Expecting " ...
          "either %<tRealPart> or %<tImagPart>."
        %<LibBlockReportError([], errTxt)>
      %endif
    %else
      %assign pValue = value[pIdx]
    %endif
     
    %% Inform the code generator of any non-finites, etc.
    %<LibCheckValue(0, pValue)>
     
    %% Return the actual value with the appropriate data type cast.
    %% need raw value to be used in a tlc expression
    %if needRawValue
      %assign theVal = ...
        SLibGetCastedValueFromId(LibGetRecordContainerDataTypeId(param), pValue)
    %else
      %assign theVal = ...
        SLibGetFormattedValueFromId(LibGetRecordContainerDataTypeId(param), pValue)
        %if TYPE(theVal) == "String"
          %assign theVal = FcnReplaceCCastWithStaticCastForCPP(theVal)
        %endif
    %endif
  %% 33+ bit are in string representation
  %elseif LibIsNonBuiltInTypeNeededForFixpt(dTypeId)
    %if complex
      %if reim == tRealPart
        %assign theVal = FcnGetNonBuiltInRe(value[pIdx])
      %elseif reim == tImagPart
        %assign theVal = FcnGetNonBuiltInIm(value[pIdx])
      %else
        %assign errTxt = "Invalid input argument (%<elIdx>). Expecting " ...
          "either %<tRealPart> or %<tImagPart>."
        %<LibBlockReportError([], errTxt)>
      %endif
    %else
      %assign theVal = value[pIdx]
    %endif
  %else
    %% Structure/opaque data type
 
    %% Must be scalar or vector
    %% - nRows must be 1 - checked above)
    %% - nCols = SIZE(prmValue, 1)
     
    %if LibDataTypeIsBus(dTypeId)
      %% For back compatibility we use data type ground value for
      %% zero initialization of bus data.
      %% For non-zero initialization we use fully defined struct parameter
       
      %assign zeroValForBusInit = [0.0]
      %if ((TYPE(value) == TYPE(zeroValForBusInit)) && ...
           (TYPE(value[pIdx]) == TYPE(zeroValForBusInit[0])))
     
        %% Zero-initialization of bus data
        %assert(param.Tunable == "no")
        %assert(SIZE(prmValue, 1) == 1)
        %assert(value == [0.0])
        %assert(ISEMPTY(sigIndexer))
     
        %assign theVal = LibGetGroundValueFromId(LibGetRecordContainerDataTypeId(param))
      %else
        %% Fully-defined structure parameter
        %assign theVal = FcnAccessModelParameter(param, sigIndexer)
      %endif
    %elseif LibIsStringDataType(dTypeId)
      %%String type constants should have value set in the model
      %%Do not use ground, use the actual value instead
      %assign theVal = FcnAccessModelParameter(param, sigIndexer)
    %else
      %assign theVal = LibGetGroundValueFromId(LibGetRecordContainerDataTypeId(param))
    %endif
  %endif
   
  %return theVal
%endfunction
 
 
 
 
%%DocFunction{ParameterFunctions}:LibBlockParameterSize=====================
%%Abstract:
%%Returnsavectorofsizetwointheformat[nRows,nCols]wherenRowsis
%%thenumberofrowsandnColsisthenumberofcolumns.
%%
%%SeeLibBlockParameterDimensionstoobtaintheoriginalparameter
%%datasize.
%%
%function LibBlockParameterSize(param) void
   
  %return SLibGetSizeOfValueFromParamRec(param)
 
%endfunction %% LibBlockParameterSize
 
 
%%DocFunction{ParameterFunctions}:LibBlockParameterDimensions===============
%%Abstract:
%%ReturnsarowvectoroflengthN,N>=1givingthedimensionsofthe
%%parameterdata.Forexample:
%%
%%%assigndims=LibBlockParameterDimensions("paramName")
%%%assignnDims=SIZE(dims,1)
%%%foreachi=nDims
%%/*Dimension%=%*/
%%%endforeach
%%
%%ThisfunctiondiffersfromLibBlockParameterSizeinthatitreturnsthe
%%dimensionsoftheparameterdatapriortoperformingcollapsingthe
%%Matrixparametertoacolumn-majorvector.Thecollapsingoccurs
%%forrun-timeparametersthathavespecifiedtheiroutputAsMatrix
%%fieldasfalse.
%%
%function LibBlockParameterDimensions(param) void
  %assign dims = LibGetRecordDimensions(param)
  %return dims
%endfunction %% LibBlockParameterDimensions
 
 
%%DocFunction{ParameterFunctions}:LibBlockParameterWidth===================
%%Abstract:
%%Returnsthenumberofelements(width)ofaparameter.
%%
%function LibBlockParameterWidth(param) void
   
  %assign dims = LibBlockParameterDimensions(param)
  %assign width = 1
   
  %foreach dimsIdx = SIZE(dims, 1)
    %assign width = width*dims[dimsIdx]
  %endforeach
   
  %return width
 
%endfunction %% LibBlockParameterWidth
 
 
%%DocFunction{ParameterFunctions}:LibBlockParameterIsComplex================
%%Abstract:
%%Returns1ifthespecifiedblockparameteriscomplex,0otherwise.
%%
%function LibBlockParameterIsComplex(param) void
  %% See Also:
  %% LibBlockInputSignalIsComplex
  %% LibBlockOutputSignalIsComplex
  %%
  %return LibGetRecordIsComplex(param)
%endfunction
 
 
%%DocFunction{ParameterFunctions}:LibBlockParameterDataTypeId===============
%%Abstract:
%%ReturnsthenumericIDcorrespondingtothedatatypeofthespecified
%%blockparameter.
%%
%function LibBlockParameterDataTypeId(param) void
  %% See Also:
  %% LibBlockParameterDataTypeName
  %% LibBlockOutputSignalDataTypeId
  %% LibBlockInputSignalDataTypeId
  %%
  %return LibGetRecordDataTypeId(param)
%endfunction
 
 
%%DocFunction{ParameterFunctions}:LibBlockParameterDataTypeName=============
%%Abstract:
%%Returnsthenameofthedatatypecorrespondingtothespecifiedblock
%%parameter.
%%
%function LibBlockParameterDataTypeName(param, reim) void
  %% See Also:
  %% LibBlockParameterDataTypeId
  %% LibBlockOutputSignalDataTypeName
  %% LibBlockInputSignalDataTypeName
  %%
  %return SLibGetRecordDataTypeName(param, reim)
%endfunction
 
 
%%DocFunction{ParameterFunctions}:LibBlockParameterString===================
%%Abstract:
%%Returnsthespecifiedblockparameterinterpretedasastring,i.e.,this
%%functionreturns:
%%
%%STRINGOF(param.Value[0])iftheparameterisarowmatrix
%%STRINGOF(param.Value)otherwise
%%
%%Note:
%%Itisanerrortoinvokethisfunctionwithamatrix-valuedparameter
%%withmorethanonerow.
%%
%%Ifyouareonlyaccessingtheparametervalue(s)using
%%LibBlockParameterStringorLibBlockParameterValue,youshouldconsider
%%convertingtheparametertoaParamSetting.Thiswillproducemore
%%efficientcodesincetheparameterwouldnotbedeclaredasavariablein
%%thecode.
%%
%function LibBlockParameterString(param) void
 
  %% See Also:
  %% Built-in TLC function STRINGOF()
 
  %assert !LibIsEnumDataType(LibGetRecordDataTypeId(param))
  %assign prmValue = SLibGetValueFromParamRec(param, TLC_FALSE)
  %assign nRows = SIZE(prmValue, 0)
 
  %if nRows > 1 || LibGetRecordIsComplex(param)
    %assign errTxt = "Cannot access the parameter %<param.Name> as a " ...
      "string because it is either complex valued or is a matrix (or both)."
    %<LibBlockReportError([], errTxt)>
  %endif
 
  %if TYPE(prmValue) == "Matrix"
    %return STRINGOF(prmValue[0])
  %else
    %return STRINGOF(prmValue)
  %endif
   
%endfunction %% LibBlockParameterString
 
 
%%DocFunction{ParameterFunctions}:LibBlockMatrixParameter===================
%%Abstract:
%%Thisfunctionreturnstheappropriatematrixparameterforablockgiven
%%therowandcolumnusercontrolvariables(rucv,cucv),loopcontrol
%%variables(rlcv,clcv),andindices(ridx,cidx).Generallyblocksshould
%%useLibBlockParameter.Ifyouhaveamatrixparameter,youshouldwriteit
%%asacolumnmajorvectorandaccessitviaLibBlockParameter.
%%
%%Note:
%%Looprollingiscurrentlynotsupported,andwillgenerateanerror
%%ifrequested(i.e.,ifeitherrlcvorclcvisnotequalto"").
%%
%%Therowandcolumnindexargumentsaresimilartotheargumentsfor
%%LibBlockParameter.Thecolumnindex(cidx)isoverloadedtohandle
%%complexnumbers.
%%
%function LibBlockMatrixParameter(param,rucv,rlcv,ridx,cucv,clcv,cidx) void
  %% See Also:
  %% LibBlockParameter, LibBlockMatrixParameterAddr
  %%
 
  %% Use expression folding indices
  %if LibBlockOutputSignalIsNonConstExpr(0)
    %assign errTxt = "The use of LibBlockMatrixParameter in the outputs " ...
      "function violates expression folding rules."
    %<LibReportFatalError(errTxt)>
  %endif
 
  %assign str = FcnGenParamExprWithCastForMatrix(param, rucv, rlcv, ridx, ...
    cucv, clcv, cidx)
  %return (str)
%endfunction %% LibBlockMatrixParameter
 
 
%%DocFunction{ParameterFunctions}:LibBlockParamSetting======================
%%Abstract:
%%Thisfunctionreturnsthestringofaspecifiedparamsettingfor
%%aspecifedblocktype.Ifyoupassanemptyblocktypeintothisfunction,
%%theparamsettingwillbeassumedtobeinthe"ParamSettings"record
%%oftheblock.Ifanon-emptyblocktypeispassedintothefunction,
%%theparamsettingswillbeassumedtobeinthe"%<Btype>ParamSettings"
%%recordofthatblock.
%%
%function LibBlockParamSetting(bType, psType) void
  %if (bType != "")
    %assign retVal = %<bType>ParamSettings.%<psType>
  %else
    %assign retVal = ParamSettings.%<psType>
  %endif
  %return (retVal)
%endfunction %% LibBlockParamSetting
 
 
%%Function:FcnGenParamExprWithCastForMatrix==================================
%%Abstract:
%%Generateanexpressionincludingafixed-pointcast(ifnecessary).
%%
%%SeeAlso:FcnGenExprForMatrix
%%
%function FcnGenParamExprWithCastForMatrix(param, rucv, rlcv, ridx, ...
  cucv, clcv, cidx)
   
  %assign paramAST = param.ASTNode
   
  %if ((paramAST.IsNonTerminal == 1) && ...
    (paramAST.ASTNode[0].IsNonTerminal == 0) && ...
    (paramAST.ASTNode[0].Op == "M_ID") && ...
    (paramAST.ASTNode[0].Identifier == "fixpt_cast"))
     
    %% This parameter requires a fixed-point cast
    %assert (paramAST.NumChildren == 4)
     
    %% Get the expression that is being cast
    %assign varAST = paramAST.ASTNode[2]
    %assign string = ...
      FcnGenExprForMatrix(varAST, rucv, rlcv, ridx, cucv, clcv, cidx)
     
    %% Get the data types "as-stored" and "as-used" for this parameter
    %switch (varAST.Op)
      %case "M_ID"
    %assign var = ::CompiledModel.ModelParameters.Parameter[varAST.ModelParameterIdx]
    %break
      %case "M_CANPRM_ID"
    %with System[HStructDeclSystemIdx].Interface
      %assign var = CanonicalPrmArgDef[varAST.CanonicalPrmArgDefIdx]
    %endwith
    %break
      %default
    %error "For fixpt_cast, ASTNode must be M_ID or M_CANPRM_ID"
    %break
    %endswitch
     
    %assign asStoredDtId = var.OriginalDataTypeIdx
    %assign asUsedDtId = param.OriginalDataTypeIdx
     
    %assign asStoredDT = FixPt_GetDataTypeFromIndex(asStoredDtId)
    %assign asUsedDT = FixPt_GetDataTypeFromIndex(asUsedDtId)
     
    %% Generate the expression with the fixed-point cast (if possible)
    %assign string = FixPt_Fix2Fix_Param_Expr(asUsedDT, string, asStoredDT)
  %else
    %assign string = ...
      FcnGenExprForMatrix(paramAST, rucv, rlcv, ridx, cucv, clcv, cidx)
  %endif
  %return (string)
%endfunction %% FcnGenParamExprWithCastForMatrix
 
 
%%Function:FcnGenExprForMatrix==============================================
%%Abstract:
%%GivenarootASTNodeandtheotherarguments,thisfunction
%%recursivelytraversestheASTandgeneratesalanguageexpression.
%%
%%Thisfunction(ascomparedtoFcnGenExpr)explicitlyassumesthatthe
%%parametersthatitisoperatingonarematricesandhencerequires
%%bothrowandcolumnaccessorindices.
%%
%%Arguments:
%%ASTNode-RootnodeofASTwhichistobeconvertedtoanexpression
%%rucv-SeedescriptioninLibBlockMatrixParameter
%%rlcv-SeedescriptioninLibBlockMatrixParameter
%%ridx-SeedescriptioninLibBlockMatrixParameter
%%cucv-SeedescriptioninLibBlockMatrixParameter
%%clcv-SeedescriptioninLibBlockMatrixParameter
%%cidx-SeedescriptioninLibBlockMatrixParameter
%%
%function FcnGenExprForMatrix(ASTNode, rucv, rlcv, ridx, cucv, clcv, cidx)
  %% See Also:
  %% LibBlockMatrixParameter, FcnGenExpr
  %%
   
  %assign retstr = ""
  %if (ASTNode.IsNonTerminal == 1)
    %% Non-terminal
    %foreach i = ASTNode.NumChildren
      %assign this_node_str = ...
    "%<FcnGenExprForMatrix(ASTNode.ASTNode[i],rucv,rlcv,ridx,cucv,clcv,cidx)>"
      %if (this_node_str == "")
        %% Can only have a null string if caller requested imaginary part of a
        %% real expression/quantity. Since we currently do not support code
        %% generation for complex parameters in expressions, we can just
        %% jump out early and let the caller handle the situation as
        %% it wants.
        %return("")
      %endif
      %assign retstr = retstr + this_node_str
    %endforeach
    %return ("(%<retstr>)")
  %else
    %% Terminal
    %assign retstr = ...
      "%<FcnConvertTerminalNodeToExprForMatrix(ASTNode,rucv,rlcv,ridx,cucv,clcv,cidx)>"
    %return (retstr)
  %endif
%endfunction
 
 
%%Function:FcnConvertTerminalNodeToExprForMatrix=============================
%%Abstract:
%%GivenaterminalASTNode,generatesaC/Adalanguageexpression
%%
%%Thisfunction(ascomparedtoFcnConvertTerminalNodeToExpr)
%%explicitlyassumesthattheparametersthatitisoperatingonare
%%matricesandhencerequiresbothrowandcolumnaccessorindices.
%%
%%Arguments:
%%ASTNode-TerminalASTnodewhichistobeconvertedtoan
%%expression
%%rucv-SeedescriptioninLibBlockMatrixParameter
%%rlcv-SeedescriptioninLibBlockMatrixParameter
%%ridx-SeedescriptioninLibBlockMatrixParameter
%%cucv-SeedescriptioninLibBlockMatrixParameter
%%clcv-SeedescriptioninLibBlockMatrixParameter
%%cidx-SeedescriptioninLibBlockMatrixParameter
%%
%function FcnConvertTerminalNodeToExprForMatrix(ASTNode,rucv,rlcv,ridx,cucv, ...
  clcv,cidx) void
  %% See Also:
  %% FcnGenExpr, FcnConvertTerminalNodeToExpr
  %%
  %% Loop rolling not supported
  %if rlcv != "" || clcv != ""
    %assign errTxt = "Loop rolling not supported for matrix parameters."
    %<LibBlockReportError([], errTxt)>
  %endif
 
  %% Split the overloaded cidx
  %assign idNum = SLibGetReimAndIdx(cidx)
  %assign reim = idNum[0]
  %assign idx = idNum[1]
   
  %% The imaginary part of a non-complex parameter is always NULL
 
  %switch(ASTNode.Op)
    %case "M_CANPRM_ID"
      %assign ident = SLibInvokeTLCInterface(SLibGetCurrentBlock(), ...
        "Param", 0, ASTNode.CanonicalPrmArgDefIdx, 0, "", "", "", "")
      %assign tlcIFv2Enabled = !ISEMPTY(ident)
      %assign canPrmArg = ...
        FcnGetCanParmArg(BlockIdx[0], ASTNode.CanonicalPrmArgDefIdx)
      %if !tlcIFv2Enabled
        %assign cross = System[BlockIdx[0]].CrossNoArgFcnBound
        %assign ident = cross ? canPrmArg.GlobalIdentifier : LibGetRecordIdentifier(canPrmArg)
      %endif
      %if (rucv != "" || cucv != "" || (reim != "" && LibGetRecordIsComplex(canPrmArg)))
        %% Determine size
    %assign dims = LibGetRecordDimensions(canPrmArg)
        %assign nRows = dims[0]
    %assign nCols = (SIZE(dims, 1) == 1) ? 1 : dims[1]
    %assign indexStr = SLibGet2DArrayIndexer(0, nRows, rucv, "", ridx, ...
      nCols, cucv, "", idx)
      %else
    %assign indexStr = ""
      %endif
      %return("%<ident>%<indexStr>")
      %%break
       
    %case "M_ID"
      %% If this is an ID node with an Identifier like
      %% int8 or sqrt, we will want to return the mapping of the MATLAB
      %% function to the C function. For now, we will just return
      %% the Identifier itself (i.e. the MATLAB <--> C mapping is 1:1)
      %if (!ISFIELD(ASTNode,"ModelParameterIdx"))
        %return("%<FcnConvertIDToFcn(ASTNode)>")
      %endif
 
      %% Fall through since remaining code is same as for other parameter types
 
    %case "SL_INLINED"
    %case "SL_NOT_INLINED"
    %case "SL_CALCULATED"
 
      %assign mdlParam = ::CompiledModel.ModelParameters.Parameter[ASTNode.ModelParameterIdx]
      %assign complex = LibGetRecordIsComplex(mdlParam)
       
      %% Check for floating-point types if integer only code
      %if PurelyIntegerCode
        %assign dTypeId = LibGetRecordDataTypeId(mdlParam)
        %if LibIsBuiltInOrCustomFloatDatatype(dTypeId)
          %<SLibCacheIntegerOnlyWarning(Name,"Parameter")>
        %endif
      %endif
       
      %% The imaginary part of a non-complex parameter is always NULL
      %if !complex && reim == tImagPart
        %return ""
      %endif
 
      %if (rucv != "" || cucv != "" || (reim != "" && complex) || ...
          (mdlParam.Tunable == "yes") || InlineParameters != 1)
 
        %% Determine size
        %assign prmSize = SLibGetSizeOfValueFromParamRec(mdlParam)
        %assign nRows = prmSize[0]
        %assign nCols = prmSize[1]
    %assign indexStr = SLibGet2DArrayIndexer(0, nRows, rucv, "", ridx, ...
                                                    nCols, cucv, "", idx)
 
    %if LibHasCustomStorage(mdlParam)
          %return LibCustomData(mdlParam,"contents",indexStr,reim)
        %elseif mdlParam.UseAccessFunctions
          %return FcnGetAccessFunctionSignalReference(mdlParam, TLC_FALSE, indexStr)
        %endif
        %assign answer = FcnGenerateNonEmptyUcvOrNonInlinedMatrixParameter(mdlParam, indexStr, reim)
      %else
        %% Return the actual value of the parameter with the appropriate data type
        %% format.
        %assign answer = FcnGenerateInlinedMatrixParameter(mdlParam, "", ridx, cidx, idx, reim)
      %endif
 
      %return answer
      %%break
 
    %default
      %assign answer = FcnConvertOperatorNodeToExpr(ASTNode)
      %return(answer)
      %%break
  %endswitch
 
%endfunction %% FcnConvertTerminalNodeToExprForMatrix
 
 
 
%%Function:FcnGenerateNonEmptyUcvOrNonInlinedMatrixParameter================
%%Abstract:
%%Generatecodeforamatrixparameterassumingeitheroneoftheucv
%%(roworcolumn)isnotequalto"",inlineparametersison,orthe
%%parameteriscomplexortunable.
%%
%%Arguments:
%%mdlParam-ParameterfromModelParametersrecord
%%indexStr-StringgeneratedbycallstoSLibGet1DArrayIndexer
%%reim-%<tRealPart>or%<tImagPart>or""
%%
%function FcnGenerateNonEmptyUcvOrNonInlinedMatrixParameter(mdlParam, ...
  indexStr, reim)
  %% See Also:
  %% FcnGenerateNonInlinedParameter, FcnGenerateNonEmptyUcvParameter
   
  %assign answer = FcnAccessModelParameter(mdlParam, indexStr)
  %if reim != "" && LibGetRecordIsComplex(mdlParam)
    %assign answer = answer + ".%<reim>"
  %endif
   
  %return (answer)
%endfunction %% FcnGenerateNonEmptyUcvOrNonInlinedMatrixParameter
 
 
%%Function:FcnGenerateInlinedMatrixParameter=================================
%%Abstract:
%%Returnsappropriatecodeforamodelparameterwiththeassumptionthat
%%inlineparametersareonandthisparameterisamatrix.
%%
%%Arguments:
%%mdlParam-ParameterfromModelParametersrecord
%%cidx-SeedescriptioninLibBlockParameter
%%ridx-SeedescriptioninLibBlockParameter
%%idx-SeedescriptioninLibBlockParameter
%%reim-%<tRealPart>or%<tImagPart>or""
%%
%function FcnGenerateInlinedMatrixParameter(mdlParam, sigIndexer, ridx, cidx, idx, reim)
  %% See Also:
  %% FcnGenerateInlinedParameter
  %%
   
  %return SLibGenModelConstPrmMacroAccess(mdlParam, sigIndexer, [%<ridx>, %<idx>], ...
    LibGetRecordIsComplex(mdlParam), reim, "Matrix")
 
%endfunction %% FcnGenerateInlinedMatrixParameter
 
 
%%Function:FcnBlockMatrixParameterAddr=======================================
%%Abstract:
%%WorkhorsefunctionforLibBlockMatrixParameterAddr.
%%
%function FcnBlockMatrixParameterAddr(param, ...
  rucv,rlcv,ridx,cucv,clcv,cidx,simpleForm) void
 
  %if rlcv != "" && clcv != ""
    %assign errTxt = "Nested loop rolling not supported for matrix " ...
      "parameter %<param.Name>"
    %<LibBlockReportError([], errTxt)>
  %endif
 
 %if ISFIELD(param, "ASTNode")
    %assign ASTNode = param.ASTNode
    %switch (ASTNode.Op)
      %case "SL_INLINED"
      %case "SL_NOT_INLINED"
      %case "SL_CALCULATED"
        %assign paramIdx = [%<ASTNode.ModelParameterIdx>, 0]
        %break
         
      %default
        %% In this case, slightly more complicated
        %% First, ensure that only terminal node in the entire AST
        %% is a single M_ID
        %% If it is not, error out.
        %assign record = FcnBlockParameterIdxMemberStr(param)
        %assert(ISFIELD(record, "param"))
        %assert(ISFIELD(record, "member"))
   
        %assign paramIdx = record.param
        %assign memberStr = record.member
        %break
    %endswitch
  %else
    %assign paramIdx = [%<param.MdlPrmIdx>, 0]
    %if param.ArgDefIdx >= 0
      %assign paramIdx = [%<param.ArgDefIdx>, 1]
    %endif
  %endif
 
  
 
  %if (paramIdx[0] == -1)
    %assign errTxt = "Can't access the address of an expression " ...
      "(%<param.String>) in %<param.Name>"
    %<LibBlockReportError([], errTxt)>
  %endif
   
  %if paramIdx[1] %% Is canonical parameter ?
    %assign ident = SLibInvokeTLCInterface(SLibGetCurrentBlock(), ...
      "Param", 0, ASTNode.CanonicalPrmArgDefIdx, 0, "", "", "", "")
    %assign tlcIFv2Enabled = !ISEMPTY(ident)
    %assign canPrmArg = FcnGetCanParmArg(BlockIdx[0], paramIdx[0])
    %assign cross = System[BlockIdx[0]].CrossNoArgFcnBound
    %assign dims = LibGetRecordDimensions(canPrmArg)
    %assign nRow = dims[0]
    %assign nCol = (SIZE(dims, 1) == 1) ? 1 : dims[1]
    %assign indexStr = ...
      SLibGet2DArrayIndexer(0,nRow,rucv,rlcv,ridx,nCol,cucv,clcv,cidx)
    %if !tlcIFv2Enabled
      %assign ident = cross ? canPrmArg.GlobalIdentifier : LibGetRecordIdentifier(canPrmArg)
    %endif
     
    %if EXISTS(memberStr) && !WHITE_SPACE(memberStr)
        %if nRow*nCol > 1 && indexStr == "[0]"
          %return "%<ident>.%<memberStr>"
        %else
          %return "&%<ident>.%<memberStr>%<indexStr>"
        %endif
    %else
      %if nRow*nCol > 1 && indexStr == "[0]"
          %return "%<ident>"
        %else
          %return "&%<ident>%<indexStr>"
        %endif
    %endif
  %endif
   
  %assign mdlParam = ::CompiledModel.ModelParameters.Parameter[paramIdx[0]]
 
  %% Check for floating-point types if integer only code
  %if PurelyIntegerCode
    %assign dTypeId = LibGetRecordDataTypeId(mdlParam)
    %if LibIsBuiltInOrCustomFloatDatatype(dTypeId)
      %<SLibCacheIntegerOnlyWarning(Name,"Parameter")>
    %endif
  %endif
   
  %assign prmSize = SLibGetSizeOfValueFromParamRec(mdlParam)
  %assign nRows = prmSize[0]
  %assign nCols = prmSize[1]
  %assign storageClass = mdlParam.StorageClass
   
 %assign indexStr = SLibGet2DArrayIndexer(0,nRows,rucv,rlcv,ridx, ...
  nCols,cucv,clcv,cidx)
  %if EXISTS(memberStr) && !WHITE_SPACE(memberStr)
      %assign indexStr = "[%<indexStr>].%<memberStr>"
  %endif
  %if (storageClass == "ImportedExternPointer") && (nRows == 1) && (nCols == 1)
    %return LibGetRecordIdentifier(mdlParam)
  %elseif storageClass == "Custom"
    %if !LibCustomDataIsAddressable(mdlParam)
      %<SLibReportErrorWithIdAndArgs("RTW:tlc:CSCParamNotAddressable", "%<LibGetRecordVarName(mdlParam)>")>
    %endif
    %return LibCustomData(mdlParam,"address",indexStr,"")
  %elseif mdlParam.UseAccessFunctions
    %return FcnGetAccessFunctionSignalReference(mdlParam, TLC_TRUE, indexStr)
  %else
    %if simpleForm && storageClass != "Auto_SFCN"
      %assign indexStr = ""
      %if EXISTS(memberStr) && !WHITE_SPACE(memberStr)
          %assign indexStr = ".%<memberStr>"
      %endif
      %assign prmStr = FcnAccessModelParameter(mdlParam, indexStr)
    %else
      %assign prmStr = FcnAccessModelParameterRef(mdlParam, indexStr)
    %endif
    %return prmStr
  %endif
 
%endfunction %% FcnBlockMatrixParameterAddr
 
 
%%DocFunction{ParameterFunctions}:LibBlockMatrixParameterAddr===============
%%Abstract:
%%Returnstheaddressofamatrixparameter.
%%
%%Note,LibBlockMatrixParameterAddrreturnstheaddressofamatrix
%%parameter.Looprollingisnotsupported(i.e.rlcvandclcvshouldboth
%%betheemptystring).
%%
%function LibBlockMatrixParameterAddr(param,rucv,rlcv,ridx,cucv,clcv,cidx) void
 
  %% See Also:
  %% LibBlockMatrixParameter, LibBlockMatrixParameterValue,
  %% LibBlockMatrixParameterBaseAddr
  %%
   
  %if LibBlockOutputSignalIsNonConstExpr(0)
    %assign errTxt = "The use of LibBlockMatrixParameterAddr in the " ...
      "outputs function violates expression folding rules. Try using " ...
      "LibBlockMatrixParameterBaseAddr."
    %<LibReportFatalError(errTxt)>
  %endif
 
  %return FcnBlockMatrixParameterAddr(param,rucv,rlcv,ridx,cucv,clcv,cidx,0)
   
%endfunction %% LibBlockMatrixParameterAddr
 
 
%%DocFunction{ParameterFunctions}:LibBlockMatrixParameterBaseAddr===========
%%Abstract:
%%Returnsthebaseaddressofamatrixparameter.
%%
%function LibBlockMatrixParameterBaseAddr(param) void
 
  %% See Also:
  %% LibBlockMatrixParameter, LibBlockMatrixParameterValue,
  %% LibBlockMatrixParameterAddr
  %%
   
  %if SLibGetWidthOfValueFromParamRec(param) > 1
    %% vectors and matrices can drop the "&" and "[0]"
    %assign simpleForm = 1
  %else
    %% scalars do not drop the "&"
    %assign simpleForm = 0
  %endif
 
  %return FcnBlockMatrixParameterAddr(param,"","",0,"","",0,simpleForm)
   
%endfunction %% LibBlockMatrixParameterBaseAddr
 
 
%%Function:FcnGetMatrixPrmValue==============================================
%%Abstract:
%%Getthevalueofthematrixparameter.
%%
%function FcnGetMatrixPrmValue(value, dTypeId, complex, ridx, cidx) void
 
  %% Split the overloaded cidx
  %assign idNum = SLibGetReimAndIdx(cidx)
  %assign reim = idNum[0]
  %assign idx = idNum[1] %%numeric part of cidx
  %return FcnGetMatrixPrmValueCore(value, dTypeId, ridx, idx, complex, reim, 1)
%endfunction %% FcnGetMatrixPrmValue
 
 
 
%%Function:FcnGetMatrixPrmValueCore===========================================
%%Abstract:
%%Gettheindexedvalueofthespecifiedmatrixmodelparameter
%%
%function FcnGetMatrixPrmValueCore(paramValue, dTypeId, ridx, cidx, complex, reim, needRawValue) void
  %% The imaginary part of a non-complex parameter is always NULL
  %if complex
    %if reim != tRealPart && reim != tImagPart
      %assign errTxt = ...
      "Since the value is complex, the caller should " ...
      "specify whether the real part or the imaginary part is to be returned."
      %<LibBlockReportFatalError([], errTxt)>
    %endif
  %elseif reim == tImagPart
    %return ""
  %endif
   
  %% Check for floating-point types if integer only code
  %if PurelyIntegerCode && LibIsBuiltInOrCustomFloatDatatype(dTypeId)
    %<SLibCacheIntegerOnlyWarning(Name,"Parameter")>
  %endif
   
  %% Determine size
  %assign nRows = SIZE(paramValue, 0)
  %assign nCols = SIZE(paramValue, 1)
 
  %% gracefully handle vectors as 1xN matrices
  %if TYPE(paramValue) != "Matrix"
    %if ridx != 0 && cidx != 0
      %<SLibReportErrorWithId("RTW:tlc:NonZeroIdx")>
    %elseif TYPE(paramValue) == "Vector"
      %if nCols == 1
        %assign cidx = 0
      %else
        %assign cidx = (ridx == 0) ? cidx : ridx
      %endif
      %assign value = paramValue[cidx]
    %else %%scalar
      %assign value = paramValue
    %endif
  %else
    %assign value = paramValue[ridx][cidx]
  %endif
   
  %if LibIsEnumDataType(dTypeId)
    %% Return enum string instead of ordinal value (cannot be complex).
    %assign theVal = SLibGetEnumTypeCodeGenStringFromIndex(dTypeId, value)
     
  %elseif (LibIsBuiltInDataType(LibGetDataTypeStorageIdFromId(dTypeId)) || ...
          LibIsHalfDataType(dTypeId))
    %% Get the value
    %if complex
      %if reim == tRealPart
        %assign pValue = REAL(value)
      %elseif reim == tImagPart
        %assign pValue = IMAG(value)
      %else
        %assign errTxt = "Invalid input argument (%<complex>). "
        "Expecting either %<tRealPart> or %<tImagPart>."
        %<LibBlockReportFatalError([], errTxt)>
      %endif
    %else
      %assign pValue = value
    %endif
     
    %% Inform the code generator of any non-finites, etc.
    %<LibCheckValue(0, pValue)>
    %if needRawValue
      %assign theVal = SLibGetCastedValueFromId(dTypeId, pValue)
    %else
      %assign answer = SLibGetFormattedValueFromId(dTypeId, pValue)
      %assign theVal = (pValue < 0) ? "(%<answer>)" : answer
    %endif
  %elseif LibIsNonBuiltInTypeNeededForFixpt(dTypeId)
    %if complex
      %if reim == tRealPart
        %assign theVal = FcnGetNonBuiltInRe(value)
      %elseif reim == tImagPart
        %assign theVal = FcnGetNonBuiltInIm(value)
      %else
        %assign errTxt = "Invalid input argument (%<complex>). "
        "Expecting either %<tRealPart> or %<tImagPart>."
        %<LibBlockReportFatalError([], errTxt)>
      %endif
    %else
      %assign theVal = value
    %endif
  %endif
   
  %return theVal
%endfunction
 
 
 
 
%%Function:LibBlockMatrixParameterValue======================================
%%Abstract:
%%Returnsthenumericvalueofamatrixparameter.
%%Ifyouareaccessingtheparametervalue(s),youshouldprobablyconvert
%%theparametertoaParamSetting.Thiswillproducemoreefficientcode.
%%
%%SeeAlso:LibBlockMatrixParameter,LibBlockParameterValue
%%
%function LibBlockMatrixParameterValue(param, ridx, cidx) void
 
  %assign prmValue = SLibGetValueFromParamRec(param, TLC_TRUE)
  %return FcnGetMatrixPrmValue(prmValue, ...
    LibGetRecordContainerDataTypeId(param), LibGetRecordIsComplex(param), ...
    ridx, cidx)
 
%endfunction %% LibBlockMatrixParameterValue
 
 
%%Function:SLibParameterValue================================================
%%Abstract:
%%Determinethenumericvalueofamatrixparameter,formatted
%%accordingtoitsdatatype.
%%
%%Arguments:
%%value:Amatrixofvalues
%%dTypeId:DatatypeIdofvaluesinmatrix
%%complex:Complexityofvaluesinmatrix
%%ridx:Rowindexintotheparametermatrix
%%cidx:Columnindexintotheparametermatrix
%%
%function SLibParameterValue(value, dTypeId, complex, ridx, cidx) void
 
  %% See Also:
  %% LibBlockMatrixParameterValue, LibBlockMatrixParameter
  %%
   
  %return FcnGetMatrixPrmValue(value, dTypeId, complex, ridx, cidx)
   
%endfunction %% SLibParameterValue
 
%%-------------------------------------------
%%Modelparameterrelatedfunctionsfollow%
%%-------------------------------------------
 
%%Function:LibModelParameterDataTypeName====================================
%%Abstract:
%%Returnthedatatypenameofthegivenmodelparameterrecord
%%(mdlParamisarecordinModelParameterstable)takinginto
%%accountthecomplexityofthemodelparameter.
%%
%function LibModelParameterDataTypeName(mdlParam)
  %if LibGetRecordIsComplex(mdlParam)
    %assign dtype = LibGetDataTypeComplexNameFromId(LibGetRecordDataTypeId(mdlParam))
  %else
    %assign dtype = LibGetDataTypeNameFromId(LibGetRecordDataTypeId(mdlParam))
  %endif
  %return (dtype)
%endfunction %% LibModelParameterDataTypeName
 
 
%%Function:SLibGetModelParameterStorageClass=================================
%%Abstract:
%%SLibGetModelParameterStorageClassreturnsthespecifiedparameter's
%%storageclass.WheremdlParamisareferencetoaparameterrecord
%%fromModelParameterstable
%%
%function SLibGetModelParameterStorageClass(mdlParam) void
  %if SLibIsLegacyStorageClassForDataRecord(mdlParam)
    %return "Custom"
  %else
    %return mdlParam.StorageClass
  %endif
%endfunction %% SLibGetModelParameterStorageClass
 
 
%%Function:SLibGetModelParameterTypeQualifier===============================
%%Abstract:
%%SLibGetModelParameterTypeQualifierreturnstheparameter's
%%typequalifier.WheremdlParamisareferencetoaparameterrecord
%%fromModelParameterstable.
%%
%function SLibGetModelParameterTypeQualifier(mdlParam) void
  %return mdlParam.TypeQualifier
%endfunction %% SLibGetModelParameterTypeQualifier
 
 
%%Function:SLibGetModelParameterIdentifier==================================
%%Abstract:
%%Getamodelparameter'sidentifierwhere
%%mdlParamisareferencetoaparameterrecordfromModelParameterstable
%%
%function SLibGetModelParameterIdentifier(mdlParam) void
  %return LibGetRecordIdentifier(mdlParam)
%endfunction %% SLibGetModelParameterIdentifier
 
 
%%Function:SLibGetModelParameterTunable======================================
%%Abstract:
%%Determineifspecifiedmodelparameteristunable.
%%
%function SLibGetModelParameterTunable(mdlParam) void
  %return mdlParam.Tunable
%endfunction %% SLibGetModelParameterTunable
 
 
%%Function:SLibGetModelParameterTunable=====================================
%%Abstract:
%%SLibGetModelParameterDataTypeIdreturnstheparameter'sdatatypeid,
%%wheremdlParamisareferencetoaparameterrecordfrom
%%ModelParameterstable.
%%
%function SLibGetModelParameterDataTypeId(mdlParam) void
  %return LibGetRecordDataTypeId(mdlParam)
%endfunction %% SLibGetModelParameterDataTypeId
 
 
%%Function:SLibGetModelParameterComplex=====================================
%%Abstract:
%%Purpose:
%%Getamodelparameter'scomplexitywhere
%%mdlParamisareferencetoaparameterrecordfromModelParameterstable
%%
%function SLibGetModelParameterComplex(mdlParam) void
  %return LibGetRecordIsComplex(mdlParam)
%endfunction %% SLibGetModelParameterComplex
 
%function FcnPropagatedParamChildGroup(mdlParam) void
  %assign key = "CG" + mdlParam.ChildGroupSID
  %assign map = ::CompiledModel.ChildGroupMap
  %return map.%<key>
%endfunction
     
%function FcnPropagatedParamChildGroupPath(mdlParam) void
  %if ISFIELD(mdlParam, "ChildGroupPath")
    %return mdlParam.ChildGroupPath
  %else
    %assign childGroup = FcnPropagatedParamChildGroup(mdlParam)
    %return childGroup.GroupPath
  %endif
%endfunction
 
%function FcnPropagatedParamGroupIndex(mdlParam) void
  %assign childGroup = FcnPropagatedParamChildGroup(mdlParam)
  %return FcnGetParentGroupIndex(childGroup)
%endfunction
 
%function FcnPropagatedParamSelfPath(mdlParam) void
  %assign childGroup = FcnPropagatedParamChildGroup(mdlParam)
  %return childGroup.SelfPath
%endfunction
 
%function FcnPropagatedParamSingleInstanceType(mdlParam) void
  %assign childGroup = FcnPropagatedParamChildGroup(mdlParam)
  %return childGroup.SingleInstanceType
%endfunction
     
%function FcnPropagatedParamSingleInstancePropagator(mdlParam) void
  %assign childGroup = FcnPropagatedParamChildGroup(mdlParam)
  %return childGroup.SingleInstancePropagator
%endfunction
     
%function FcnPropagatedParamSingleInstanceDefiner(mdlParam) void
  %assign childGroup = FcnPropagatedParamChildGroup(mdlParam)
  %return childGroup.SingleInstanceDefiner
%endfunction
     
%%Function:FcnParamExternalPath===============================================
%%Abstract:
%%Purpose:
%%Returnpathtogroupedmodelargfromchildfromanexternalcontext
%%
%function FcnParamExternalPath(mdlParam) void
  %if !SLibMultiInstance()
    %assign path = FcnPropagatedParamChildGroupPath(mdlParam)
  %else
    %assign groupIndex = FcnPropagatedParamGroupIndex(mdlParam)
    %assign path = SLibCoderDataGroupInstance(::CompiledModel.CoderDataGroup[groupIndex]) ...
      + "." + FcnPropagatedParamChildGroupPath(mdlParam)
  %endif
  %return path
%endfunction
 
%%Function:FcnParamInternalPath===============================================
%%Abstract:
%%Purpose:
%%Returnpathtogroupedmodelargfromchildfromaninternalcontext
%%
%function FcnParamInternalPath(mdlParam, isLocal) void
  %if isLocal
      %assign ownerSysIdx = mdlParam.OwnerSysIdx[0]
      %assign ownerSys = ::CompiledModel.System[ownerSysIdx]
      %assign instIdx = mdlParam.OwnerSysIdx[1]
 
      %% Get the model reference from mdlParan
      %assign coderGroup = FcnPropagatedParamChildGroup(mdlParam)
      %assign modelrefBlk = ::CompiledModel.ModelReferenceBlocks[coderGroup.CompiledModelBlockIndex]
      %assign blk = ::CompiledModel.System[modelrefBlk[0]].Block[modelrefBlk[1]]
      %assign blkInterface = GetModelrefInterface(blk)
      %assign pathToMdlBlkDWork = FcnGetChildCoderGroupDWorkPathFromSys(blk, blkInterface, instIdx, ownerSysIdx)
      %assign childCoderGroup = ...
        blkInterface.CoderDataGroups.CoderDataGroup[coderGroup.IndexInBlockInterface]
      %return pathToMdlBlkDWork + "." + childCoderGroup.SelfPath
  %elseif SLibMultiInstance()
    %assign childGroupPath = FcnPropagatedParamChildGroupPath(mdlParam)
    %if IsModelReferenceSimTarget()
      %assign baseSystem = System[GetBaseSystemIdx()]
      %<LibAccessArg(baseSystem.Interface.DWorkArgDef)>
      %return "localDW->" + FEVAL("extractAfter",childGroupPath,"rtdw.")
    %elseif GenerateClassInterface
      %% InstP is a private data field in C++ class interface
      %assign groupIndex = FcnPropagatedParamGroupIndex(mdlParam)
      %assign group = ::CompiledModel.CoderDataGroup[groupIndex]
      %assign vgIdx = SLibGetRootVarGroupIdxForCoderGroup(group)
      %return SLibCGIRVarGroupPath(vgIdx, GetBaseSystemIdx(), TLC_FALSE) + childGroupPath
    %else
      %assign groupIndex = FcnPropagatedParamGroupIndex(mdlParam)
      %return SLibGetCoderDataGroupStructPtr(groupIndex) + "->" + childGroupPath
    %endif
  %else
    %return FcnParamExternalPath(mdlParam)
  %endif
%endfunction
 
%%Function:SLibIsGroupedModelArgFromChildModel
%%Abstract:
%%Purpose:
%%Isthisagroupedmodelargfromchildmodel
%%
%function SLibIsGroupedModelArgFromChildModel(mdlParam) void
  %return ISFIELD(mdlParam, "ChildGroupSID") && !ISFIELD(mdlParam, "VarGroupIdx")
%endfunction
   
%%Function:SLibHasGroupedModelArgFromChildModel
%%Abstract:
%%Purpose:
%%Doesthismodelhaveagroupedmodelargfromchildmodel
%%
%function SLibHasGroupedModelArgFromChildModel() void
  %foreach paramIdx = ::CompiledModel.ModelParameters.NumParameters
    %assign param = ::CompiledModel.ModelParameters.Parameter[paramIdx]
    %if SLibIsGroupedModelArgFromChildModel(param)
      %return TLC_TRUE
    %endif
  %endforeach
  %return TLC_FALSE
%endfunction
 
%%Function:SLibGetGroupedParamQualifiedIdentifier=============================
%%Abstract:
%%Purpose:
%%Returnidentifierforpotentiallygroupedmodelargument
%%
%function SLibGetGroupedParamQualifiedIdentifier(mdlParam) void
  %assign tokens = FEVAL("strsplit", mdlParam.Identifier, ".")
  %assign varName = tokens[SIZE(tokens)[1] - 1]
  %if SLibIsGroupedModelArgFromChildModel(mdlParam)
    %assign ownerSys = ::CompiledModel.System[mdlParam.OwnerSysIdx[0]]
    %assign isLocal = (ownerSys.RTWSystemCode == 2) && !IsBaseSystem(ownerSys)
    %if isLocal
      %assign deref = IsModelReferenceSimTarget() ? "." : "->"
      %return FcnParamInternalPath(mdlParam, isLocal) + deref + varName
    %elseif IsModelReferenceSimTarget()
      %return FcnParamInternalPath(mdlParam, isLocal)
    %else
      %return FcnParamInternalPath(mdlParam, isLocal) + "." + varName
    %endif
  %else
    %return varName
  %endif
%endfunction
 
 
 
 
%%Function:FcnAccessModelParameterIdentifier===========================
%%Abstract:
%%Thisfunctionsreturnstheparameteridentifierforparameters
%%However,thisfunctionallowsyoutocontrolwhetheryouwantthevalueor
%%thereferencetothespecifiedsigIndexer.
%%FcnAccessModelParameterwilljustgiveyouthevalueoftheparameter,
%%FcnAccessModelParameterRefwillgiveyoutheaddresstotheparameter.However,
%%&P.a[0]becomesP.a.
%function FcnAccessModelParameterIdentifier(mdlParam, sigIndexer, getRef) void
  %assign mdlParam.WasAccessedAsVariable = 1
  %assign idNum = IDNUM(mdlParam.LogicalSrc)
  %assign mdlParamIdx = idNum[1]
   
  %assign useIndex = TLC_TRUE
  %if getRef && CanUseSimpleReferenceFormat(mdlParam, sigIndexer)
    %assign useIndex = TLC_FALSE
  %endif
   
  %if EXISTS(BlockIdx)
    %assign ident = SLibInvokeTLCInterface(SLibGetCurrentBlock(), ...
      "Param", 1, mdlParamIdx, useIndex && getRef, "", "", "", "")
    %assign tlcIFv2Enabled = !ISEMPTY(ident)
    %if tlcIFv2Enabled
      %if useIndex
        %return ident + sigIndexer
      %else
        %return ident
      %endif
    %endif
  %endif
   
  %assign useIndex = TLC_TRUE
  %if getRef && CanUseSimpleReferenceFormat(mdlParam, sigIndexer)
    %assign useIndex = TLC_FALSE
  %endif
   
  %switch mdlParam.StorageClass
    %case "Auto_SFCN"
      %assign dtName = ...
        LibGetDataTypeNameFromId(SLibGetModelParameterDataTypeId(mdlParam))
      %if WHITE_SPACE(sigIndexer)
        %assign prmId = "(*(%<dtName> *)(mxGetData(%<LibGetRecordIdentifier(mdlParam)>" + ...
          "(%<RTMGetModelSS()>))))"
        %assert useIndex == TLC_TRUE
      %else
        %assign prmId = "((%<dtName> *)mxGetData(%<LibGetRecordIdentifier(mdlParam)>" + ...
          "(%<RTMGetModelSS()>)))"
        %if useIndex
          %assign prmId = "(" + prmId + sigIndexer + ")"
        %endif
        %if getRef && useIndex
          %return "&" + prmId
        %else
          %return prmId
        %endif
      %endif
      %break
    %case "Auto"
      %if SLibIsGroupedModelArgFromChildModel(mdlParam)
        %assign prmId = SLibGetGroupedParamQualifiedIdentifier(mdlParam)
      %else
        %assign prmId = FcnGetAutoParamIdentifier(mdlParam)
      %endif
      %break
    %case "ExportedGlobal"
      %assign prmId = LibGetRecordIdentifier(mdlParam)
      %break
    %case "ImportedExtern"
      %assign prmId = LibGetRecordIdentifier(mdlParam)
      %if (mdlParam.DefinedInLegacyCode != 0) && (mdlParam.LegacyDimensions > 1)
        %assign legacyIndexer = ""
        %foreach i = mdlParam.LegacyDimensions
          %assign legacyIndexer = legacyIndexer + "[0]"
        %endforeach
        %assign prmId = "(&" + prmIdx + legacyIndexer + ")"
      %endif
      %break
    %case "ImportedExternPointer"
      %assign prmId = LibGetRecordIdentifier(mdlParam)
      %if !getRef && WHITE_SPACE(sigIndexer)
        %assign prmId = "(*" + prmId + ")"
      %endif
      %break
    %case "Custom"
       
      %<LibReportFatalError("Assert: Should not be here")>
      %break
    %default
       
      %assign errTxt = "Unknown storage class in FcnAccessModelParameter: " ...
        "%<mdlParam.StorageClass>"
      %<LibReportFatalError(errTxt)>
      %break
  %endswitch
 
  %if getRef
    %if useIndex
      %return "&" + prmId + sigIndexer
    %else
      %return prmId
    %endif
  %else
    %return prmId + sigIndexer
  %endif
%endfunction
 
%%Function:FcnAccessModelParameterRef=======================================
%%Abstract:
%%Thisfunctionreturnsthereferencetoaparameter.However,itissmarter.
%%e.g.,forscalars,thisfucntionsreturns&P.a,or&P.b[3].However,forvectors,
%%thisfunctionreturnsp.binsteadof&p.b[0].
%function FcnAccessModelParameterRef(mdlParam, sigIndexer) void
   
  %return FcnAccessModelParameterIdentifier(mdlParam, sigIndexer, TLC_TRUE)
   
%endfunction
 
%%Function:FcnAccessModelParameter===========================================
%%Abstract:
%%FcnAccessModelParameterreturnsthepropervalueforaparameter
%%accordingtoitsstorageclass,where
%%mdlParamisareferencetoaparameterrecordfromModelParameterstable
%%andsigIndexeristheoptionalwidth(index)specifier.
%%
%function FcnAccessModelParameter(mdlParam, sigIndexer) void
   
  %return FcnAccessModelParameterIdentifier(mdlParam, sigIndexer, TLC_FALSE)
 
%endfunction %% FcnAccessModelParameter
 
%function CanUseSimpleReferenceFormat(mdlParam, sigIndexer) void
%%Abstract:
%%determinewhethershouldgenerateP.afor&P.a[0].
%assign prmSize = LibBlockParameterSize(mdlParam)
%assert TYPE(sigIndexer) == "String"
%if ((prmSize[0]*prmSize[1] > 1) && !ISEMPTY(sigIndexer) && sigIndexer == "[0]") && ...
    !LibGetRecordIsStdContainer(mdlParam)
  %return TLC_TRUE
%else
  %return TLC_FALSE
%endif
%endfunction
 
 
%%Function:FcnGetStructFieldAccesser
%%Abstract:
%%FcnGetStructFieldAccesserretunsthecorrectstringforreferencinga
%%memberofthegiven(struct)modelparameter.Thismethodusesthe
%%parameter'sstorageclasstodetermineifthisshouldbedirectaccess
%%orpointeraccess.
%%
%%Forexample,ifthiswerecalledformodel(structure)parameterP
%%withImportedExternPointerstorageclasswitharequestforfield'a',
%%wewouldreturn"->a"
%%
%function FcnGetStructFieldAccesser(mdlParam, memberStr)
  %assign accesser = ""
   
  %if ISEMPTY(memberStr)
    %return accesser
  %endif
   
  %switch (mdlParam.StorageClass)
    %case "Auto"
    %case "ExportedGlobal"
    %case "ImportedExtern"
      %assign accesser = "."
      %break
    %case "ImportedExternPointer"
      %assign accesser = "->"
      %break
    %case "Custom"
      %assign dataAccess = SLibGetDataAccess(SLibGetCSCDefForData(mdlParam), mdlParam)
      %if (dataAccess == "Pointer")
        %assign accesser = "->"
      %elseif (dataAccess == "Direct")
        %assign accesser = "."
      %else
        %<LibReportFatalError("Assert: Non addressable structure reference for CSC")>
      %endif
      %break
    %case "Auto_SFCN"
    %default
      %assign errTxt = "Unknown storage class in FcnGetStructFieldAccesser: " ...
        "%<mdlParam.StorageClass>"
      %<LibReportFatalError(errTxt)>
  %endswitch
   
    %return "%<accesser>%<memberStr>"
%endfunction
 
%%Function:FcnAccessStructModelParameterIdentifier===========================
%%Abstract:
%%FcnAccessStructModelParameterIdentifierreturns:thevalue,thereference
%%(forexample,&P.a[3]orP.a(eq.to&P.a[0]))
%%
%%
%function FcnAccessStructModelParameterIdentifier(mdlParam, param, memberStr, ...
  sigIndexer, getRef) void
  %assign mdlParam.WasAccessedAsVariable = 1
   
  %assign accesserStr = ""
  %if (memberStr != "")
    %assign accesserStr = FcnGetStructFieldAccesser(mdlParam, memberStr)
  %endif
   
  %switch mdlParam.StorageClass
       
    %case "Auto"
      %assign prmIdentifier = FcnGetAutoParamIdentifier(mdlParam) + accesserStr
      %break
       
    %case "ExportedGlobal"
      %assign prmIdentifier = LibGetRecordIdentifier(mdlParam) + accesserStr
      %break
       
    %case "ImportedExtern"
      %assign prmIdentifier = LibGetRecordIdentifier(mdlParam) + accesserStr
      %if (mdlParam.DefinedInLegacyCode != 0) && (mdlParam.LegacyDimensions > 1)
        %assign legacyIndexer = ""
        %foreach i = mdlParam.LegacyDimensions
          %assign legacyIndexer = legacyIndexer + "[0]"
        %endforeach
        %assign prmIdentifier = "(&" + prmIdentifier + legacyIndexer +")"
      %endif
      %break
       
    %case "ImportedExternPointer"
       
      %if (SLibGetWidthOfValueFromParamRec(mdlParam) == 1) && (memberStr == "")
        %return "(*%<LibGetRecordIdentifier(mdlParam)>)"
      %else
        %assign prmIdentifier = LibGetRecordIdentifier(mdlParam) + accesserStr
      %endif
      %break
       
    %case "Custom"
 
      %<LibReportFatalError("Assert: Should not be here")>
      %break
       
    %case "Auto_SFCN"
    %default
       
      %assign errTxt = "Unknown storage class in FcnAccessStructModelParameter: " ...
        "%<mdlParam.StorageClass>"
      %<LibReportFatalError(errTxt)>
      %break
  %endswitch
   
  %if getRef
    %if CanUseSimpleReferenceFormat(param, sigIndexer)
      %return prmIdentifier
    %else
      %return "&(" + prmIdentifier + sigIndexer + ")"
    %endif
  %else
    %return prmIdentifier + sigIndexer
  %endif
%endfunction %% FcnAccessStructModelParameterIdentifier
 
%%Function:FcnAccessStructModelParameterRef==================================
%%FcnAccessStructModelParameterRefreturnstheproperreferenceforaparameter
%%accordingtoitsstorageclass,where
%%mdlParamisareferencetoaparameterrecordfromModelParameterstable
%%andsigIndexeristheoptionalwidth(index)specifier.
%function FcnAccessStructModelParameterRef(mdlParam, param, memberStr, sigIndexer) void
  %return FcnAccessStructModelParameterIdentifier(mdlParam, param, memberStr, sigIndexer, TLC_TRUE)
%endfunction %%FcnAccessStructModelParameterRef
 
%%Function:FcnConstParamUsesChecksumName
%%Abstract:
%%Thisfunctionreturnswhethertheparametershouldusethechecksum-based
%%nameforitsusage.Ifit'saccessedoutsideasharedfunction,thenuse
%%thenicename.
%function FcnConstParamUsesChecksumName(mdlParam)
  %% If it's accessed outside of ashared function, then it does not use the checksum
  %% name.
  %if SLibConstParamAccessedOutsideSharedFcn(mdlParam)
    %return TLC_FALSE
  %else
    %return TLC_TRUE
  %endif
%endfunction %%FcnConstParamUsesChecksumName
   
 
%%Function:FcnGetAutoParamIdentifier=========================================
%%Abstract:
%%Thisfunctionreturnsaidentifierwithoutindexerforparametersofauto
%%storageclass.
%%
%function FcnGetAutoParamIdentifier(mdlParam)
  %if SLibGenConstRTPForPrm(mdlParam)
    %% If it's unstructured const param, append rtCP_
    %if SLibIsUnstructuredConstParam(mdlParam)
      %if FcnConstParamUsesChecksumName(mdlParam)
        %assign firstParam = ::CompiledModel.ModelParameters.Parameter[mdlParam.FirstInstanceConstIdx]
        %assign csName = firstParam.ChecksumName
        %return "%<tUnstructConstParameters>_%<csName>"
      %else
        %if ISFIELD(mdlParam,"TruncatedId")
            %return "%<mdlParam.TruncatedId>"
        %else
            %assign identifier = "rtCP_" + LibGetRecordIdentifier(mdlParam)
            %assign remLength = ::CompiledModel.ConfigSet.MaxIdLength
            %if SIZE(identifier)[1] <= remLength
                %assign truncatedMdlPrm = identifier
            %else
                %assign truncatedMdlPrm = LibRequestIDWithLength(identifier, TLC_TRUE, TLC_FALSE, remLength)
            %endif
            %addtorecord mdlParam TruncatedId truncatedMdlPrm
            %return "%<mdlParam.TruncatedId>"
        %endif
      %endif
    %else
      %return "%<::tConstParamStruct>%<ConstPQualifier>%<LibGetRecordIdentifier(mdlParam)>"
    %endif
  %elseif SLibGenConstPrmWithInit(mdlParam)
    %return "%<::tConstParamWithInitStruct>%<ConstPQualifier>%<LibGetRecordIdentifier(mdlParam)>"
  %elseif SLibIsParamUnstructured(mdlParam)
    %return "%<tUnstructParameters>_%<LibGetRecordIdentifier(mdlParam)>"
  %else
    %assign sigSrc = mdlParam.OwnerSysIdx
    %if ISFIELD(mdlParam, "VarGroupIdx")
      %assign varGroupIdx = mdlParam.VarGroupIdx[0]
    %else
      %assign varGroupIdx = FcnSysVarGroupIndex(System[sigSrc[0]], "Parameter", sigSrc[1])
    %endif
    %if EXISTS("HStructDeclSystemIdx")
      %assign prmArgDef = System[HStructDeclSystemIdx].Interface.ParameterArgDef
      %%
      %% Does a passthrough parameter structure argument exists ?
      %%
      %if prmArgDef.PassthroughSystemIdx > -1
    %<SLibAccessArgHelper(System[HStructDeclSystemIdx].Interface.ParameterArgDef,"",FcnGetCurrentAccessTid())>
    %%
    %% Return the parameter idenfifier of a passthrough parameter argument
    %%
        %assign accSysIdx = GenerateClassInterface ? ...
          HStructDeclSystemIdx : prmArgDef.PassthroughSystemIdx
        %assign cross = ((MultiInstanceERTCode && !GenerateClassInterface) || isGRTMallocOnERT()) && !FcnParamsAreGlobalStruct() ? CrossNoArgFcnBound : TLC_FALSE
        %assign prmPath = SLibCGIRVarGroupPath(varGroupIdx, ...
          System[accSysIdx].NonInlinedParentSystemIdx, ...
          cross)
      %else
        %assign rtwModule = RTWCGModules.RTWCGModule[System[HStructDeclSystemIdx].CGIRModuleIdx]
        %assign cross = CrossNoArgFcnBound
        %assign prmPath = ...
          SLibCGIRVarGroupPath(varGroupIdx, ...
          System[HStructDeclSystemIdx].NonInlinedParentSystemIdx, ...
          cross)
      %endif
    %else
      %%
      %% If a parameter identifier is generated outside of a system scope
      %% (e.g. ert s-function) we generate the full identifier path
      %%
      %assign baseSysIdx = GetBaseSystemIdx()
      %assign prmPath = ...
        SLibCGIRVarGroupPath(varGroupIdx, baseSysIdx, 0)
    %endif
    %return prmPath + LibGetRecordIdentifier(mdlParam)
  %endif
%endfunction
 
 
%%Function:SLibGenBlockPrmReference==========================================
%%Abstract:
%%Usedmainlybythefixed-pointblocksettogenerateareferenceto
%%ablockparameter
%function SLibGenBlockPrmReference(blockParam, sigIndexer) void
  %assign paramIdx = FcnGetModelParamIdxFromBlockParam(blockParam)
  %if (paramIdx == -1)
    %assign errTxt = "Cannot access identifier of expression " ...
      "%<blockParam.String>."
    %<LibBlockReportFatalError([], errTxt)>
  %endif
  %assign mdlParam = ::CompiledModel.ModelParameters.Parameter[paramIdx]
  %assert (mdlParam.StorageClass == "Auto")
  %return FcnAccessModelParameter(mdlParam, sigIndexer)
%endfunction
 
 
%%------------------------------------------%
%%Blockparameterrelatedfunctionsfollow%
%%------------------------------------------%
 
%%Function:SLibGetBlockParameterStorageClass=================================
%%Abstract:
%%Getablockparameter'sstorageclasswhere
%%blockParamisareferencetoablockparameter.
%%
%function SLibGetBlockParameterStorageClass(blockParam) void
  %assign paramIdx = FcnGetModelParamIdxFromBlockParam(blockParam)
  %if (paramIdx == -1)
    %assign errTxt = "Cannot access storage class of expression " ...
      "%<blockParam.String>."
    %<LibBlockReportFatalError([], errTxt)>
  %endif
 
  %assign mdlParam = ::CompiledModel.ModelParameters.Parameter[paramIdx]
  %return (SLibGetModelParameterStorageClass(mdlParam))
%endfunction %% SLibGetBlockParameterStorageClass
 
 
%%Function:SLibGetBlockParameterTypeQualifier================================
%%Abstract:
%%Getablockparameter'stypequalifierwhere
%%blockParamisareferencetoablockparameter.%%
%%
%function SLibGetBlockParameterTypeQualifier(blockParam) void
  %assign paramIdx = FcnGetModelParamIdxFromBlockParam(blockParam)
  %if (paramIdx == -1)
    %assign errTxt = "Cannot access type qualifier of expression " ...
      "%<blockParam.String>"
    %<LibBlockReportFatalError([], errTxt)>
  %endif
 
  %assign mdlParam = ::CompiledModel.ModelParameters.Parameter[paramIdx]
  %return (SLibGetModelParameterTypeQualifier(mdlParam))
%endfunction %% SLibGetBlockParameterTypeQualifier
 
 
%%Function:SLibGetBlockParameterIdentifier==================================
%%Abstract:
%%Getablockparameter'sidentifierwhere
%%blockParamisareferencetoablockparameter
%%
%function SLibGetBlockParameterIdentifier(blockParam) void
  %assign paramIdx = FcnGetModelParamIdxFromBlockParam(blockParam)
  %if (paramIdx == -1)
    %assign errTxt = "Cannot access identifier of expression " ...
      "%<param.String>."
    %<LibBlockReportFatalError([], errTxt)>
  %endif
 
  %assign mdlParam = ::CompiledModel.ModelParameters.Parameter[paramIdx]
  %return (SLibGetModelParameterIdentifier(mdlParam))
%endfunction %% SLibGetBlockParameterIdentifier
 
 
%%Function:SLibBlockParameterIsTunable=======================================
%%Abstract:
%%Tobecalledbyablockmethod(e.g.theOutputsfunction)todetermine
%%ifthespecifiedparameteristunable.Thisalwaysreturnstrue(1)
%%ifinlineparametersisoff,otherwiseforinlineparameterson,
%%itwillreturntrueiftheparameterfieldhasareferenceto
%%atunableparameter.
%%
%%Forexample:Inlineparametersonandparametercontains'a'*'b'where
%%either'a'or'b'orbothareinthetunableparametersdialog
%%thenthespecifiedparameterisconsideredtunable(1).
%%
%function SLibBlockParameterIsTunable(blockParam) void
  %assign paramIdx = FcnGetModelParamIdxFromBlockParam(blockParam)
  %if (paramIdx == -1)
    %% This can only occur when we have a multiple references to
    %% tunable parameters (inline parameters has to be on for
    %% this to occur).
    %return 1
  %endif
 
  %return ::CompiledModel.ModelParameters.Parameter[paramIdx].Tunable == "yes"
   
%endfunction %% SLibBlockParameterIsTunable
 
 
%%Function:FcnGetModelParamIdxFromBlockParam================================
%%Abstract:
%%Purpose:
%%Givenablockparameter,returntheparameter'sindexintothemodel
%%parametertable.IftheparametercorrespondstoanASTforan
%%expression,thenreturn-1.
%%
%%Arguments:
%%blockParam:Referencetoablockparameter
%%
%function FcnGetModelParamIdxFromBlockParam(blockParam) void
  %if ISFIELD(blockParam, "ASTNode")
    %assign ASTNode = blockParam.ASTNode
    %switch (ASTNode.Op)
      %case "SL_INLINED"
      %case "SL_NOT_INLINED"
      %case "SL_CALCULATED"
        %return ASTNode.ModelParameterIdx
         
      %default
        %% In this case, slightly more complicated
        %% First, ensure that only terminal node in the entire AST
        %% is a single M_ID
        %% If it is not, error out.
        %assign paramIdx = FcnGetUniqueNode(ASTNode)
        %if paramIdx[1] %% Is canonical parameter
          %return (-1)
        %else
          %return paramIdx[0]
        %endif
    %endswitch
  %else
    %return blockParam.MdlPrmIdx
  %endif
%endfunction %% FcnGetModelParamIdxFromBlockParam
 
 
%%Function:SLibGetAllASTParamsForBlockParam=================================
%%Abstract:
%%SLibGetAllASTParamsForBlockParamgeneratesavectorwiththemodel
%%parameterindexofallparametersintheASTofthegivenblock
%%parameter.
%%
%function SLibGetAllASTParamsForBlockParam(blockParam)
  %return(%<FcnGetAllParamsFromASTNode(blockParam.ASTNode)>)
%endfunction %% SLibGetAllASTParamsForBlockParam
 
 
%%Function:FcnGetAllParamsFromASTNode=======================================
%%Abstract:
%%FcnGetAllParamsFromASTNodegeneratesavectorwiththemodel
%%parameterindexofallparametersinthegivenAST.
%%
%function FcnGetAllParamsFromASTNode(ASTNode)
  %if (ASTNode.IsNonTerminal == 1)
    %% Non-terminal
    %assign allParams = []
    %foreach i = ASTNode.NumChildren
      %% Get parameters from i'th child
      %assign childParams = FcnGetAllParamsFromASTNode(ASTNode.ASTNode[i])
      %if (TYPE(childParams) == "Vector")
        %foreach j = SIZE(childParams, 1)
          %% Check each entry. If it's -1, then ignore it. Else, add it
          %% to our list.
          %if (childParams[j] != -1)
            %assign allParams = allParams + childParams[j]
          %endif
        %endforeach
      %else
        %% If the child simply returned a scalar, check it's value and add it
        %% to our list if appropriate
        %if (childParams != -1)
          %assign allParams = allParams + childParams
        %endif
      %endif
    %endforeach
    %% Remove duplicate parameters in array
    %assign returnParams = []
    %foreach i = SIZE(allParams, 1)
      %assign found = 0
      %foreach j = SIZE(returnParams, 1)
        %if (returnParams[j] == allParams[i])
          %assign found = 1
        %endif
      %endforeach
      %if (!found)
        %assign returnParams = returnParams + allParams[i]
      %endif
    %endforeach
    %% Return our list to the parent (or caller, as appropriate)
    %return(returnParams)
  %else
    %% Terminal
    %switch(ASTNode.Op)
      %case "M_ID"
      %case "M_CANPRM_ID"
      %case "SL_INLINED"
      %case "SL_NOT_INLINED"
      %case "SL_CALCULATED"
        %% These are the only nodes that can contain parameters
        %if (ISFIELD(ASTNode,"ModelParameterIdx"))
          %return(ASTNode.ModelParameterIdx)
        %else
          %% One could have an M_ID field like 'int8' or 'sin'
          %% but these are not parameters
          %return(-1)
        %endif
        %break
 
      %default
        %return(-1)
        %%break
 
    %endswitch
  %endif
%endfunction %% FcnGetAllParamsFromASTNode
 
 
%%-----------------------------------%
%%ASTNoderelatedfunctionsfollow%
%%-----------------------------------%
 
%%Function:LibBlockParameterIsExpression====================================
%%Abstract:
%%Thisfunctiondeterminesiftheparameterisanexpression.
%%
%function LibBlockParameterIsExpression(param)
  %if ISFIELD(param, "ASTNode")
    %assign ASTNode = param.ASTNode
    %assign paramIdx = FcnGetUniqueNode(ASTNode)
    %if (paramIdx[0] == -1 || paramIdx[1])
      %% Ensure that it's not an SL_INLINED, SL_CALCULATED, or SL_NOT_INLINED
      %% node
      %if ((ASTNode.Op == "SL_INLINED") || ...
        (ASTNode.Op == "SL_NOT_INLINED") || ...
        (ASTNode.Op == "SL_CALCULATED") || ...
        (ASTNode.Op == "M_CANPRM_ID"))
        %assign isExpr = 0
      %else
        %assign isExpr = 1
      %endif
    %else
      %assign isExpr = 0
    %endif
    %return (isExpr)
  %else
    %return param.MdlPrmIdx < 0 && param.ArgDefIdx < 0
  %endif
%endfunction %% LibIsExpression
 
 
%%Function:SLibGetASTNodeIsComplex==========================================
%%Abstract:
%%ReturnthecomplexityofanASTNode.Note,eveniftheASTnodeisa
%%functionsuchas'+'or'sin',thisfunctionwillreturn0.
%%
%function SLibGetASTNodeIsComplex(ASTNode)
  %if (ISFIELD(ASTNode,"ModelParameterIdx"))
    %assign mdlParamIdx = ASTNode.ModelParameterIdx
    %assign mdlParam = ModelParameters.Parameter[mdlParamIdx]
    %return LibGetRecordIsComplex(mdlParam)
  %else
    %return 0
  %endif
%endfunction %% SLibGetASTNodeIsComplex
 
 
%%Function:SLibGetASTNodeDataTypeId=========================================
%%Abstract:
%%AccessorfunctiontogetdatatypeofanASTnode.
%%Note,iftheASTnodeisafunctionsuchas'+'or'sin',thisfunction
%%willreturntSS_DOUBLE.
%function SLibGetASTNodeDataTypeId(ASTNode)
  %if (ISFIELD(ASTNode,"ModelParameterIdx"))
    %assign mdlParamIdx = ASTNode.ModelParameterIdx
    %assign mdlParam = ::CompiledModel.ModelParameters.Parameter[mdlParamIdx]
    %return LibGetRecordDataTypeId(mdlParam)
  %else
    %return(tSS_DOUBLE)
  %endif
%endfunction %% SLibGetASTNodeDataTypeId
 
 
%%Function:FcnGetUniqueNode=================================================
%%Abstract:
%%SearchesanASTformodelparameterandcanonicalidentifiernodes.
%%
%%Thisfunctionreturn:
%%
%%[-1,0]iftheASThasmorethanoneterminal
%%node(isanexpression).
%%[modelparameterindex,0]iftheASThasonlyoneterminalnodeand
%%theterminalnodeistheidentifierofa
%%modelwideparameter
%%[canonicalparamindex,1]iftheASThasonlyoneterminalnodeand
%%theterminalnodeistheidentifierofa
%%canonicalparameter(passedtothesystem
%%asanargument)
%%
%function FcnGetUniqueNode(ASTNode)
  %assign idx = [-1, 0]
  %if (ASTNode.IsNonTerminal == 1)
    %% Non-terminal
    %foreach i = ASTNode.NumChildren
      %assign origIdx = idx
      %% Search children
      %assign idx = FcnGetUniqueNode(ASTNode.ASTNode[i])
      %%
      %if (idx[0] == -1)
        %% Found a non M_ID node; Generate an error
        %return [-1, 0]
      %elseif (origIdx[0] != -1 && idx[0] != -1)
        %% Found two identifiers in this tree; Generate an error
        %return [-1, 0]
      %endif
    %endforeach
    %return(idx)
  %else
    %% Terminal
    %if (ASTNode.Op != "M_ID" && ASTNode.Op != "M_CANPRM_ID")
      %return [-1, 0]
    %else
      %% Node is an identifier
      %if (ISFIELD(ASTNode,"ModelParameterIdx"))
        %return [%<ASTNode.ModelParameterIdx>, 0]
      %elseif (ISFIELD(ASTNode,"CanonicalPrmArgDefIdx"))
    %return [%<ASTNode.CanonicalPrmArgDefIdx>, 1]
      %else
        %return [-1, 0]
      %endif
    %endif
  %endif
%endfunction %% FcnGetUniqueNode
 
%%Function:FcnGetValueFromTermASTNode======================================
%function FcnGetValueFromTermASTNode(ASTNode)
  %if ISFIELD(ASTNode, "Value")
    %assign result = ASTNode.Value
  %elseif ISFIELD(ASTNode, "ModelParameterIdx")
    %assign result = ModelParameters.Parameter[ASTNode.ModelParameterIdx].Value
  %else
    %assign result = []
  %endif
  %if SIZE(result) == [1,1]
    %assign result = result[0]
  %endif
  %return result
%endfunction %% FcnGetValueFromTermASTNode
 
 
%%Function:FcnGetDirectStructReferenceNode===================================
%%Abstract:
%%FortheASTtreecorespondingtodirectstructreference'a.b.c'
%%thisfunctionreturnsrecord:
%%{Node,pathpathElem[]}
%%whereNodeisaASTNodeforthestructparamidentifier'a'
%%pathisamemberStr-'b.c'
%%pathElemarrayofpathelementnames-parsedmemberStr
%%{name'b'}
%%{name'c'}
%%
%function FcnGetDirectStructReferenceNode(ASTNode)
%createrecord ASTNodePath {Node %<ASTNode>; path ""}
%if (ASTNode.IsNonTerminal != 1)
  %return ASTNodePath
%endif
%%3children
%if (ASTNode.NumChildren != 3)
  %return ASTNodePath
%endif
%%2ndand3rdshouldbeterminal
%if ((ASTNode.ASTNode[1].IsNonTerminal == 1) || (ASTNode.ASTNode[2].IsNonTerminal == 1))
  %return ASTNodePath
%endif
%%2ndand3rdshouldbeM_DOTM_ID
%if ((ASTNode.ASTNode[1].Op != "M_DOT") || (ASTNode.ASTNode[2].Op != "M_ID"))
  %return ASTNodePath
%endif
%%1stshouldbeDotifNon-TerminalorM_ID/M_CANPRM_IDifterminal
%if ((ASTNode.ASTNode[0].IsNonTerminal != 1) && ...
     ((ASTNode.ASTNode[0].Op == "M_ID") ||(ASTNode.ASTNode[0].Op == "M_CANPRM_ID") ))
  %assign ASTTermNode = ASTNode.ASTNode[0]
  %assign ASTNodePath.Node = ASTTermNode
  %assign ASTNodePath.path = "%"
  %addtorecord ASTNodePath pathElem {name "%"}
  %return ASTNodePath
%endif
%if ((ASTNode.ASTNode[0].IsNonTerminal == 1) && (ASTNode.ASTNode[0].Op == "Dot"))
  %assign ASTNodePath = FcnGetDirectStructReferenceNode(ASTNode.ASTNode[0])
  %if (ASTNodePath.path != "")
    %assign ASTNodePath.path = "%<ASTNodePath.path>" + "." + "%"
    %addtorecord ASTNodePath pathElem {name "%"}
  %endif
  %return ASTNodePath
%endif
%%%%%%%%newcodeforhandling"ArraysofStructs"usecase
%%Aparametercouldbeanarrayofstructanditcouldhaveindices.This
%%casehandlesthoseindicesgoingdowntoanylevelofarraystructaccess.
%%E.g.:a(1).b(2).c(3).d(4)etc.
%if ((ASTNode.ASTNode[0].IsNonTerminal == 1) && (ASTNode.ASTNode[0].Op == "Subsref"))
  %% First confirm if the ASTNode at this level has a value that is to
  %% to be used as an array index.
  %assign ArraySel = ASTNode.ASTNode[0].NumChildren == 4 && ...
                ASTNode.ASTNode[0].ASTNode[1].Op == "M_LRB" && ...
                ASTNode.ASTNode[0].ASTNode[3].Op == "M_RRB"
  %if ArraySel
    %assign childNode = ASTNode.ASTNode[0].ASTNode[0]
 
    %% If the node indeed has a array index associated with it,
    %% two cases arise:
    %% Case 1: The node is terminal node and hence contains Array
    %% index of the main Tunable Parameter. Add this array index
    %% to the ASTNodePath to be used later.
    %if(childNode.IsNonTerminal == 0)
      %assign ASTNodePath.Node = childNode
      %assign ASTNodePath.path = "%"
      %assign indValue = CAST("Number", FcnGetValueFromTermASTNode(ASTNode.ASTNode[0].ASTNode[2])) - 1
      %addtorecord ASTNodePath pathElem {name "%"}
      %addtorecord ASTNodePath baseParamIndex indValue
    %else
      %% Case 2: The node is a substruct in the hierarchy and the associated
      %% array index is the index for this particular sub-struct node. Build
      %% this path up now itself using the identifier information and
      %%previous path information
      %assign ASTNodePath = FcnGetDirectStructReferenceNode(childNode)
      %if (ASTNodePath.path != "")
        %assign indValue = CAST("Number",FcnGetValueFromTermASTNode(ASTNode.ASTNode[0].ASTNode[2])) - 1
        %assign ASTNodePath.path = "%<ASTNodePath.path>" + "[" + "%<indValue>" + "]" + "." + "%"
        %addtorecord ASTNodePath pathElem {name "%"}
      %endif
    %endif
  %endif
  %return ASTNodePath
%endif
%%%%%%%%
%return ASTNodePath
%endfunction %% FcnGetDirectStructReferenceNode
 
%endif %% _PARAMLIB_
 
%%[EOF]paramlib.tlc