%% %% Abstract: %% RTW target file for N-Port Matrix Multiply block. %% %% $RCSfile: sdspmmult2.tlc,v $ %% $Revision: 1.6 $ $Date: 2000/06/15 20:37:45 $ %% %% Copyright 1995-2000 The MathWorks, Inc. %implements sdspmmult2 "C" %include "dsplib.tlc" %% Function: BlockInstanceSetup ================================================== %% %function BlockInstanceSetup(block, system) void %endfunction %% BlockInstanceSetup %% %% For two matrices, %% MatMultRR(out, in1, in2, dims); %% MatMultCC(out, in1, in2, dims); %% MatMultRC(out, in1, in2, dims); %% MatMultCR(out, in1, in2, dims); %% %% MatMultDD(out, in1, in2, dims); %% MatMultZZ(out, in1, in2, dims); %% MatMultDZ(out, in1, in2, dims); %% MatMultZD(out, in1, in2, dims); %% Function: getMatMultFcnName ================================================== %% Abstract: %% Produces fcn names according to the following convention: %% %% S = single, %% C = single complex %% D = Double %% Z = Double complex %% %% Examples: %% MatMultDD - two real, double-precision inputs %% MatMultSC - 1st input is real single, 2nd is complex single %% %% NOTE: Inputs are either both single or both double. %% No cross-type support is provided. %% %function getMatMultFcnName(A_Cplx, B_Cplx, DTypeId) void %switch DTypeId %case tSS_DOUBLE %if A_Cplx && B_Cplx %assign cplx = "ZZ" %elseif A_Cplx && !B_Cplx %assign cplx = "ZD" %elseif !A_Cplx && B_Cplx %assign cplx = "DZ" %else %assign cplx = "DD" %endif %break %case tSS_SINGLE %if A_Cplx && B_Cplx %assign cplx = "CC" %elseif A_Cplx && !B_Cplx %assign cplx = "CS" %elseif !A_Cplx && B_Cplx %assign cplx = "SC" %else %assign cplx = "SS" %endif %break %default %error "Data type not handled." %endswitch %return "MatMult" + cplx %endfunction %% getMatMultFcnName %% Function: getRealOrComplexDataType ============================================= %% Abstract: %% %function getRealOrComplexDataType(DTypeId, Cplx) %return (Cplx) ? LibGetDataTypeComplexNameFromId(DTypeId) \ : LibGetDataTypeNameFromId(DTypeId) %endfunction %% getRealOrComplexDataType %% Function: getMatMultFcnProto =============================================== %% Abstract: %% Return the matrix multiplication function call prototype, given %% the input port complexities and the data type. %% %% Example: %% Assume A is real, B is complex, and we have double-precision data. %% The function prototype in this situation is: %% %% "MatMultDZ(creal64_T *y, real64_T *A, creal64_T *B, const int dims[3])" %% %function getMatMultFcnProto(A_Cplx, B_Cplx, DTypeId) void %assign A_type = getRealOrComplexDataType(DTypeId, A_Cplx) %assign B_type = getRealOrComplexDataType(DTypeId, B_Cplx) %assign out_type = (A_Cplx) ? A_type : B_type %assign fcn_arg_proto = "(" + out_type + " *y, " + A_type + " *A, " + B_type + " *B, const int dims[3])" %assign fcn_proto = "void " + getMatMultFcnName(A_Cplx, B_Cplx, DTypeId) + fcn_arg_proto %return fcn_proto %endfunction %% getMatMultFcnProto %% Function: GenerateMatMultFcnComment ======================================== %% Abstract: %function GenerateMatMultFcnComment(A_Cplx, B_Cplx, DTypeId) Output %% Generate comment: %assign c1 = (A_Cplx) ? "Complex" : "Real" %assign c2 = (B_Cplx) ? "Complex" : "Real" %% %% %assign in_type = getRealOrComplexDataType(DTypeId, 0) %% %switch DTypeId %case tSS_DOUBLE %assign slang = "double-precision" %break %case tSS_SINGLE %assign slang = "single-precision" %break %default %error "Unsupported data type encountered: id = %" %endswitch %% /* * Function: % * Abstract: * DSP Blockset 2-input matrix multiply function * Input 1: %, % %% % * Input 2: %, % %% % */ %endfunction %% GenerateMatMultFcnComment %% Function: GenerateMatMultFcnBody ============================================== %% Abstract: %% Generate the body of the matrix multiplication function, including %% starting and ending braces. %% %function GenerateMatMultFcnBody(A_Cplx, B_Cplx, DTypeId) Output %% %assign A_type = getRealOrComplexDataType(DTypeId, A_Cplx) %assign B_type = getRealOrComplexDataType(DTypeId, B_Cplx) %% %assign out_Cplx = (A_Cplx || B_Cplx) %assign out_type = getRealOrComplexDataType(DTypeId, out_Cplx) %assign out_real_type = getRealOrComplexDataType(DTypeId, 0) %% { %% int k; for(k=dims[2]; k-- > 0; ) { %% % *A1 = A; int i; for(i=dims[0]; i-- > 0; ) { % *A2 = A1++; % *B1 = B; %% %if out_Cplx % acc; int j; acc.re = (%)0.0; acc.im = (%)0.0; %else % acc = (%)0.0; int j; %endif %% for(j=dims[1]; j-- > 0; ) { %% %if !A_Cplx && !B_Cplx %% %% Real, Real: %% acc += *A2 * *B1++; A2 += dims[0]; } *y++ = acc; } B += dims[1]; %% %elseif !A_Cplx && B_Cplx %% %% Real, Complex: %% acc.re += *A2 * B1->re; acc.im += *A2 * (B1++)->im; A2 += dims[0]; } *y++ = acc; } B += dims[1]; %% %elseif A_Cplx && !B_Cplx %% %% Complex, Real: %% acc.re += A2->re * *B1; acc.im += A2->im * *B1++; A2 += dims[0]; } *y++ = acc; } B += dims[1]; %% %else %% %% Complex, Complex: %% % A2_val = *A2; % B1_val = *B1++; acc.re += CMULT_RE(A2_val, B1_val); acc.im += CMULT_IM(A2_val, B1_val); A2 += dims[0]; } *y++ = acc; } B += dims[1]; %% %endif %% %% } %% end k-loop } %% end function scope %% %endfunction %% GenerateMatMultFcnBody %% Function: RenderMatMultFcn ============================================== %% Abstract: %% Render the RenderMatMultFcn function and prototype. %% Only render the content ONCE. Any additional calls %% are simply ignored. %% %% Returns the function name as a convenience to the caller. %% %% CplxIn1, CplxIn2: Complexity of each of the two input ports (0 or 1) %% dataType: Either "single" or "double" %% %function RenderMatMultFcn(A_Cplx, B_Cplx, DTypeId) %assign fcn_name = getMatMultFcnName(A_Cplx, B_Cplx, DTypeId) %assign database_entry = "sdspmmult2_" + fcn_name + "_fcn" %assign model_cache = "::CompiledModel." + database_entry %% Check info so that we do not define this function more than once: %if !EXISTS("%") %% Retain definition to prevent multiple identical defines: %% %assign % = 1 %assign ::CompiledModel = ::CompiledModel + % %undef % %% Remove from block scope %assign fcn_proto = getMatMultFcnProto(A_Cplx, B_Cplx, DTypeId) %% Cache the function prototype %% %openfile buffer %\ extern %; %closefile buffer % %% Cache the matrix mult function itself: %% %openfile buffer %\ extern % % %closefile buffer % %endif %return fcn_name %endfunction %% RenderMatMultFcn %% Function: getIOPtr ========================================================= %% Abstract: %% Determine the storage area of an input, output, or temp matrix %% based on the IO Index. 0 = output, >0 = input, <0 = temp (DWork) %% %function getIOPtr(block, idx, cplx) void %assign DTypeId = LibBlockOutputSignalDataTypeId(0) %assign ptrType = "% *" %if idx < 0 %% Temp storage area %assign dwName = "Temp" + STRING(-idx) %assign dwRef = % %assign ptr = "(%)" + LibBlockDWorkAddr(dwRef,"","",0) %elseif idx == 0 %% Output port %assign ptr = "(%)" + LibBlockOutputSignalAddr(0,"","",0) %else %% Input port %% Translate from 1,2,... to 0,1,... %assign ptr = "(%)" + LibBlockInputSignalAddr(idx-1,"","",0) %endif %return ptr %endfunction %% getIOPtr %% Function: GenerateTwoInputMultiply ======================================== %% Abstract: %% %% %function GenerateTwoInputMultiply(block, pairNum) Output %% %assign A_Cplx = IO_Complex[pairNum][0] %assign B_Cplx = IO_Complex[pairNum][1] %assign out_Cplx = IO_Complex[pairNum][2] %assign DType = LibBlockOutputSignalDataTypeId(0) %% %assign A_Ptr = getIOPtr(block, IO_Index[pairNum][0], A_Cplx) %assign B_Ptr = getIOPtr(block, IO_Index[pairNum][1], B_Cplx) %assign out_Ptr = getIOPtr(block, IO_Index[pairNum][2], out_Cplx) %% %assign fcnName = RenderMatMultFcn(A_Cplx, B_Cplx, DType) %% %(%, %, %, &dims[%][0]); %% %endfunction %% GenerateTwoInputMultiply %% Function: CreateStaticDimsArray ============================================= %% %function CreateStaticDimsArray(block) void %assign rows = SIZE(IO_Index,0) %assign decl = "static const int dims[%][3] = {" %foreach pairNum = rows %assign decl = decl + "{%, %, %}" %if (pairNum < rows-1) %assign decl = decl + ", " %endif %endforeach %assign decl = decl + "};" %return decl %endfunction %% CreateStaticDimsArray %% Function: Outputs ========================================================== %% %function Outputs(block, system) Output %% /* DSP Blockset N-Port Matrix Multiply (%) - % */ %% %assign numSteps = CAST("Number", %) %if numSteps>0 %assign rows = SIZE(IO_Index,0) %assign cols = SIZE(IO_Index,1) { % %foreach idx = rows % %endforeach } %else %% One input - just copy input to output if needed %% %assign need_copy = (LibBlockInputSignalBufferDstPort(0) != 0) %if need_copy %% %assign DTypeId = LibBlockOutputSignalDataTypeId(0) %assign numEle = LibBlockInputSignalWidth(0) %% %if LibBlockInputSignalIsComplex(0) %% Twice as many elements when complex: %assign numEle = numEle * 2 %endif memcpy(%, %, \ %); %else /* (no action necessary since buffer is reused) */ %endif %endif %% %endfunction %% [EOF] sdspmmult2.tlc