%% %% Function-Call Code Generation for the DSP Blockset %% %% dsp_cgargs.tlc - Code-generation partition option functions %% common to block-parameters and port-properties. %% %% Author: D. Orofino %% Copyright (c) 1995-1999 The MathWorks, Inc. All Rights Reserved. %% $Revision: 1.13 $ % $Date: 2000/04/19 19:39:45 $ %if EXISTS("_dsp_cgargs_") == 0 %assign _dsp_cgargs_ = 1 %include "dsp_iolists.tlc" %% Function: AnyCGArgs ================================================ %% Abstract: %% Determine if any partition options have been selected. %% %function AnyCGArgs(block) void %foreach idx = NumCGFcnArgs %if CGFcnArgs[idx].value %return 1 %endif %endforeach %return 0 %endfunction %% AnyCGArgs %% Function: CGArgListForFcnCall ================================================ %% Abstract: %% Returns the list of non-inlined function partition options. %% A leading comma (but no trailing comma) is returned, or an %% empty string. %% %% Ex: If we're not inlining the port complexity and width, and %% all block properties are inlined. In this case, the arg %% list is ",\n0,64", assuming cplx=0 and width=64. %% %% Note: One leading carriage-return is added to the arg list to %% make it easier to read. If all port-props and block-params %% are inlined, an empty string is returned. %% %function CGArgListForFcnCall(block,system, xArgs) void %assign portprop = PortPropArgListForFcnCall(block, xArgs) %assign blkparam = BlkParamArgListForFcnCall(block, xArgs) %assign c = (WHITE_SPACE(portprop) || WHITE_SPACE(blkparam)) ? "" : ",\n" %assign argList = portprop + c + blkparam %return argList %endfunction %% CGArgListForFcnCall %% Function: CGArgListForFcnCallProto ========================================= %% Abstract: %% Generate "optional argument" list for function-call interface. %% Generates C prototype, i.e., it includes datatype declarations. %% %% Note: A carriage-return is used before each arg in the list to %% make it easier to read. If all port-props and block-params %% are inlined, an empty string is returned. %% %function CGArgListForFcnCallProto(block,system, xArgs) void %assign portprop = PortPropArgListForFcnCallProto(block, xArgs) %assign blkparam = BlkParamArgListForFcnCallProto(block, xArgs) %assign c = (WHITE_SPACE(portprop)|| WHITE_SPACE(blkparam)) ? "" : ",\n" %assign argList = portprop + c + blkparam %return argList %endfunction %% CGArgListForFcnCallProto %% Function: DSPAddCGFcnArgsToBlock ============================================== %% Abstract: %% %% Create multiple CGFcnArg records, one for each code-gen %% function argument structure, and add to the block record. %% Each CGFcnArg record has a param, value, and dtype field. %% The values are obtained from the M-file database. %% %% Add the descriptive s-function name to the block record. %% %% This is part of the "initialization" call dispatched %% from the BlockInstanceSetup fcn. %% %function DSPAddCGFcnArgsToBlock(block) void %% xxx Consider adding to block/s-fcn, and not to each and every %% block instance. Note that we don't have to include this %% info for each "fcn partition" (there may be more than one %% function per block/S-fcn), since the partition-parameters %% themselves are block-specific. %% %% This is a memory efficiency issue. %% Add name of code-gen options file to block %% and to system if one was not already defined. %% It could have been previously defined if the %% "code-gen fcn call config" block was added to %% the model. %% %if !EXISTS("CGOptsFile") % %assign CGOptsFile = "dsp_cgopts" %assign ::CompiledModel = ::CompiledModel + CGOptsFile %endif % %% Add number of port-partition properties to block record: %% %assign NumCGPortProps = FEVAL("dsp_cgfc",block,"NumPortProps") %assign block = block + NumCGPortProps %% Add number of CGFcnArgs records to block: %% %assign NumCGFcnArgs = FEVAL("dsp_cgfc",block,"NumFcnVars") %assign block = block + NumCGFcnArgs %% Cache code-partitioning options into the block record: %% %% xxx NOTE: Would rather pass a structure directly from MATLAB %% back to TLC, but that currently is not supported. %% Instead, we must reconstruct our own record here: %% %foreach i = NumCGFcnArgs %% %% param: string name of parameter %% value: boolean indicating if user chose to split fcn calls on this param %% dtype: string name of data type ("int_T", etc) %% setting: instance-specific value of the corresponding param %% %assign Xparam = FEVAL("dsp_cgfc", block, "GetFcnVarParam", i+1) %assign Xvalue = FEVAL("dsp_cgfc", block, "GetFcnVarValue", i+1) %assign Xdtype = FEVAL("dsp_cgfc", block, "GetFcnVarDType", i+1) %assign Xinfo = FEVAL("dsp_cgfc", block, "GetFcnVarInfo", i+1) %assign XparamStr = "%" %if !EXISTS("%") %assign msg = "Function partition parameter '%' is not defined.\n\n" \ + "This may be due to a parameter that has been defined in " \ + "the database but not added to the block record.\n\n" \ + "- Run 'dsp_cgpref' and check that the information " \ + "in the code generation database is correct.\n\n" \ + "- Check that the block TLC file is adding variable " \ + "'%' to the block record in the " \ + "BlockInstanceSetup() function." %exit % %endif %assign Xsetting = % % %endforeach %% Add descriptive S-Function name to the block record %% for use in comment generation, etc. %% %assign CGBlockName = FEVAL("dsp_cgfc", block, "GetBlockName") %assign block = block + CGBlockName %endfunction %% DSPAddCGFcnArgsToBlock %% Function: DSPAddCGBlockRecord ======================================================== %% Abstract: %% Needed only to get a new variable scope in order to add %% multiple records to the block record. %% %function DSPAddCGBlockRecord(block, param, value, dtype, ... info, setting) void %% Must add records within a separate function %% scope or a scoping-error will occur! %% %% NOTE: All args are strings (edit box strings); %% %% If the parameter is a string then it needs to be a string. %if TYPE(setting) == "String" %assign temp = CGFcnArgs \ {param "%"; value %; dtype "%"; \ info "%"; setting "%"} %else %assign temp = CGFcnArgs \ {param "%"; value %; dtype "%"; \ info "%"; setting %} %endif %assign block = block + CGFcnArgs %endfunction %% DSPAddCGBlockRecord %% Function: Need2CreateFcn_cache ============================================== %% Abstract: %% Cached copy of the "need2CreateFcn" call to the MATLAB database %% for the current block. %% %% The answer may only be cached for this instance itself. %% The first block of this "partition class" will answer true; %% all others in the class will answer false. %% %% So why cache this just for this one instance? %% The call is somewhat expensive, and is called once per %% "mdl section" participating in function-call code gen. %% %% Ex: if you have start/ic/update/output sections, that %% would be 4 calls. Only 1 needs to perform the actual query. %% %function Need2CreateFcn_cache(block) void %if !EXISTS("block.need2CreateFcn") %assign need2CreateFcn = FEVAL("dsp_cgfc",block,"need2CreateFcn") %assign block = block + need2CreateFcn %endif %return block.need2CreateFcn %endfunction %% Need2CreateFcn_cache %% Function: GetFcnCallSerialNum ============================================== %% Abstract: %% Determine unique serial # string for this partition of the S-Function %% %% Function-call partitions are the variations of the function %% that are generated for a given S-Function. For example, if %% the S-Fcn code is being partitioned on complexity, then if %% two instances of the block exist and one is real while the %% other is complex, 2 partitions will be formed, and hence, 2 %% functions generated for the same S-Fcn (one to handle the %% real case, the other to handle the complex case). %% %% The first partition, say real, is serial #1, the second #2. %% %% These serial #'s are used to generate the function call names. %% %function GetFcnCallSerialNum(block) void %% Generate serial numbers for all blocks %% if they haven't been generated yet: %% %assign blockSerialNum = CAST("Number", FEVAL("dsp_cgfc",block,"getPartitionClass")) %if blockSerialNum == -1 %error Block partition class not computed %endif %% if serial # is 0, don't generate a serial # string %% %return (blockSerialNum < 1) ? "" : STRING(blockSerialNum) %endfunction %% GetFcnCallSerialNum %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Making a record for the IO, DIP, and multi parameters %% will tightly couple the info about them. This will %% allow us to more easily exlcude certain arguments %% and enable us to generate the info for them once. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %function DSPCGFcnArgs2(block) void %% %% Generate argument list structure for functions %% to use when creating their argument lists. %% %% We only need to build the argument list once %% This function may get called multiple times %if !EXISTS("DSPFcnArgList") %with block %%%%%%%%%%%%%%%%%%%%%% %% IO Pointer Arg List %assign useVoid = MultipleIODataTypes() %% INPUTS %foreach i = NumDataInputPorts %assign inDType = (useVoid) ? "void" : LibBlockInputSignalDataTypeName(i,"") % *")> %endforeach %% OUTPUTS %foreach i = NumDataOutputPorts %assign outDType = (useVoid) ? "void" : LibBlockOutputSignalDataTypeName(i,"") % *")> %endforeach %%%%%%%%%%%%%%%%%%%%%%% %% DIP Works Arg List %% DWORKS %foreach i = NumDWork %assign dworkName = "dw_" + DWork[i].Name %assign dworkValue= LibBlockDWorkAddr(DWork[i],"","",0) %assign dworkType = LibBlockDWorkDataTypeName(DWork[i], "") + " *" % %endforeach %% IWORKS %if (NumIWorkDefines > 0) %foreach i = NumIWorkDefines %assign iworkName = "iw_" + IWorkDefine[i].Name %assign iworkValue= LibBlockIWork(IWorkDefine[i],"","",0) % %endforeach %elseif IWork[0] > 0 %exit % %endif %% PWORKS %if (NumPWorkDefines > 0) %foreach i = NumPWorkDefines %assign pworkName = "pw_" + PWorkDefine[i].Name %assign pworkValue= LibBlockPWork(PWorkDefine[i],"","",0) % %endforeach %elseif PWork[0] > 0 %exit % %endif %endwith %endif %endfunction %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%function DSPAddFcnArgList2Block(block, param, value, dtype, xArgs) void %% Abstract: %% Needed only to get a new variable scope in order to add %% multiple records to the block record. %% %function DSPAddFcnArgList2Block(block, param, value, dtype) void %assign temp = DSPFcnArgList {param "%"; value "%"; dtype "%" } %assign block = block + DSPFcnArgList %endfunction %% DSPAddFcnArgList2Block %% Function: DSPArgListForFcnCall ============================================== %% Abstract: %% Generate output and input pointer lists for function call %% argument list, in that order. %% %function DSPArgListForFcnCall(block,system, xArgs) void %assign ArgStr = "" %assign first = 1 %foreach i = SIZE(DSPFcnArgList,1) %assign Arg = DSPFcnArgList[i] %if !FEVAL("dsp_cgargnotused",Arg.param,xArgs) %assign c = (first==1) ? "" : "," %assign first = 0 %assign ArgStr = ArgStr + c + "\n" + Arg.value %endif %endforeach %return ArgStr %endfunction %% DSPArgListForFcnCall %% Function: DSPArgListForFcnCallProto ========================================= %% Abstract: %% Generate output and input pointer lists for function call %% prototype argument list, in that order. %% %function DSPArgListForFcnCallProto(block,system, xArgs) void %assign ArgStr = "" %assign first = 1 %foreach i = SIZE(DSPFcnArgList,1) %assign Arg = DSPFcnArgList[i] %if !FEVAL("dsp_cgargnotused",Arg.param,xArgs) %assign c = (first==1) ? "" : "," %assign first = 0 %assign ArgStr = ArgStr + c + "\n" + Arg.dtype + Arg.param %endif %endforeach %return ArgStr %endfunction %% DSPArgListForFcnCallProto %% Function: DSPArgListInlineDeclare ========================================== %% Abstract: %% Generate declarations of input and output pointers if the core code %% is being inlined. Each pointer is declared on a separate line, with %% all output pointers declared first, then the input pointers. %% %% These should not be generated in the core code if the code is used as a %% function call, as the pointers are then passed directly through the %% function interface. %% %function DSPArgListInlineDeclare(block, xArgs) Output %% %with block %if CGInlineFcn %foreach i = SIZE(DSPFcnArgList,1) %assign Arg = DSPFcnArgList[i] %if !FEVAL("dsp_cgargnotused",Arg.param,xArgs) %assign declare = "%% = %;" % %endif %endforeach %endif %endwith %% %endfunction %% DSPDeclareInlinedArg %% Function: WorkError ======================================================= %% Abstract: %% %function WorkError(workType) void %assign blockName = LibUnmangledPathName(Name) %assign msg = "% is being used by block %.\n" \ + "You must write the work vector to the RTW file in\n"\ + "the mdlRTW function using ssWriteRTWWorkVect()." %return msg %endfunction %% WorkError %endif %% _dsp_cgargs_ %% [EOF] dsp_cgargs.tlc