Mercurial > hg > ltpda
view m-toolbox/m/gui/gltpda/ltpdasim.m @ 0:f0afece42f48
Import.
author | Daniele Nicolodi <nicolodi@science.unitn.it> |
---|---|
date | Wed, 23 Nov 2011 19:22:13 +0100 |
parents | |
children |
line wrap: on
line source
function ltpdasim(block) % This is the automatic function wrapper % ======================================================================== % ==================== level-2 M file S-function ========================= % ======================================================================== % This wrapper is the automatic function, called by every function block % in Simulink, able to execute m-file functions retrieving from Simulink: % (1) the pointer to the object(s) to be analyzed, coming in as input of % the corresponding block (ie, the DATA), % (2) the name of the function to be applied on those data, from the tag % of the currently executed block (ie, the true FUNCTION), % (3) the parameters for that particular block, retrieved from the global % shared workspace by the handle of the block (ie, the PARAMETERS). % % The output is then generated as: % OUTPUT = FUNCTION(DATA,PARAMETERS) % % This output in the end is saved into the global array containing all % the AOs (ie, all the DATA go together with other data): thus this output % will be freely accessible by all the other functions. % % The only real output to Simulink will be just the ordinal number of the % so-generated AO into the global array of AOs. % % $Id: ltpdasim.m,v 1.37 2008/12/01 20:03:51 nicola Exp $ setup(block); %% Setup function setup(block) % Register dialog parameter: none, because they're retrieved directly % from the memory. This will prevent the user to modify the parameters % outside the proper parameters panel: block.NumDialogPrms = 0; % Register number of input and output ports block.NumInputPorts = 1; block.NumOutputPorts = 1; % Setup functional port properties to dynamically inherited. block.SetPreCompInpPortInfoToDynamic; block.InputPort(1).DirectFeedthrough = true; block.InputPort(1).DatatypeID = 0; block.InputPort(1).Complexity = 0; block.OutputPort(1).DatatypeID = 0; block.OutputPort(1).Complexity = 0; block.SampleTimes = [0 0]; block.SetAccelRunOnTLC(false); block.OutputPort(1).Dimensions = 1; % Register methods block.RegBlockMethod('SetInputPortSamplingMode',@SetInpPortFrameData); block.RegBlockMethod('SetInputPortDimensions', @SetInpPortDims); block.RegBlockMethod('Outputs', @Outputs); function SetInpPortFrameData(block, idx, fd) %#ok<INUSL> block.InputPort(1).SamplingMode = fd; block.OutputPort(1).SamplingMode = fd; function SetInpPortDims(block, idx, di) block.InputPort(idx).Dimensions = di; %% Outputs function Outputs(block) global LTPDAinvar gl loop execModels %#ok<NUSED> % disp(['The name of the currently executed block is ',get_param(get_param(gcbh,'Parent'),'Name')]) % disp(['The current size of LTPDAinvar is ',num2str(size(LTPDAinvar,1))]) currparent = get_param(gcbh,'Parent'); subsyshandle = get_param(currparent, 'handle'); % Check if it's a partial execution: if ismember('executionList',evalin('base','who')) executionList = evalin('base','executionList'); blockIndex = -1; for i=1:size(executionList,1), if executionList(i)==gcbh, blockIndex = i; break; end; end if blockIndex == -1 % this block is not included in the list of those to be executed. disp([' . Partial execution: block ',get_param(subsyshandle,'Name'),' will be skipped.']) block.OutputPort(1).Data = -1; return else % Check if the block must receive data from Simulink or retrieve them from a previous calculation: if block.InputPort(1).Data(1)==-1 annotation = find_system(bdroot,'FindAll','on','Type','Annotation','Tag','ltpda model'); execHistory = get_param(annotation,'UserData'); blockIndex = -1; for i=1:size(execHistory,1), if execHistory{i,2}==subsyshandle, blockIndex = i; end; end if blockIndex == -1 % something's wrong: the selected block is not included in the previous execution history warning(['*** Partial execution: impossible to retrieve inputs. The block ',get_param(subsyshandle,'Name'),' seems to have never been executed.']) block.OutputPort(1).Data = -1; return end j=3; while ~isempty(execHistory{blockIndex,j}) block.InputPort(1).Data(j-2) = execHistory{blockIndex,j}; j = j+1; end disp([' . Partial execution: block ',get_param(subsyshandle,'Name'),' will now be executed with data retrieved from previous calculation.']) else disp([' . Partial execution: block ',get_param(subsyshandle,'Name'),' will now be executed.']) end end end % Check if the user wants to stop the execution: lastChar = get(findobj('Name','LTPDA Progress Bar'),'CurrentCharacter'); if ~isempty(lastChar) && strcmp(lastChar,'x') set_param(bdroot, 'SimulationCommand', 'stop') return end % Update the progress bar window: progressBar = findobj('Tag','progressaxes'); if ~isempty(progressBar) blocksTotal = get(findobj('Tag','blockstotal'),'UserData'); blocksDone = get(findobj('Tag','done'),'UserData'); blocksToGo = get(findobj('Tag','togo'),'UserData'); set(findobj('Tag','done'),'UserData',blocksDone+1); set(findobj('Tag','togo'),'UserData',blocksToGo-1); set(findobj('Tag','done'),'String',['Done: ',num2str(blocksDone+1)]); set(findobj('Tag','togo'),'String',['To go: ',num2str(blocksToGo-1)]); currblockname = get_param(get_param(gcbh,'Parent'),'Name'); for i=1:numel(currblockname), if double(currblockname(i))==10, currblockname(i)=' '; end; end set(findobj('Tag','currentexec'),'String',['Current block: ',currblockname]); progressSize = get(progressBar,'UserData'); progressPosition = get(progressBar,'Position'); progressPosition(3) = 1+(progressSize(3)/blocksTotal)*(blocksDone+1); set(progressBar,'Position',progressPosition) progressBarLoop = findobj('Tag','progressaxes2'); if ~isempty(progressBarLoop) set(findobj('Tag','done'),'String',['Blocks done: ',num2str(blocksDone+1)]); loopStatus = getappdata(0,'loopStatus'); progressSize = get(progressBarLoop,'UserData'); progressLoopPosition = get(progressBarLoop,'Position'); progressLoopPosition(3) = 1+(progressSize(3)/loopStatus(1))*loopStatus(2); set(progressBarLoop,'Position',progressLoopPosition) end drawnow end % Retrieve the function name from the block tag: blocktag = get_param(gcb, 'tag'); if strcmp(blocktag,'generic') paramcommand = get_param(get_param(get_param(gcbh,'Parent'), 'handle'),'Description'); eval(paramcommand) blocktag = functionName; end % ======================================================================== %% For arithmetic blocks % ======================================================================== if strcmp(blocktag,'arithmetic') eq = get_param(currparent,'MaskDescription'); if strcmp(eq,'Arithmetic block: the user can type in the desidered equation.') disp(sprintf('Error: in the ''%s'' arithmetic block no equation has been typed in.',get_param(currparent,'Name'))) close(findobj('Name','LTPDA Progress Bar')) error(['Error: in the ',get_param(currparent,'Name'),' arithmetic block no equation has been typed in.']) end equation = eq; equation(strfind(equation,char(10))) = []; paramcommand = get_param(subsyshandle,'Description'); if isempty(paramcommand), paramcommand = 'params=plist(''alpha'',''-->'',''beta'',''-->'');'; end eval(paramcommand) for i=1:nparams(params) inputBlock = find_system(currparent,'SearchDepth',1,'LookUnderMasks','all','Name',lower(params.params(i).key)); if numel(inputBlock)>1, inputBlock(1)=[]; end % this can happen only when the currparent has the same name: then, ignore the 1st, ie. the currparent itself inputNumb = get_param(inputBlock{1},'Tag'); equation = strrep(equation,lower(params.params(i).key),['LTPDAinvar{block.InputPort(1).Data(',inputNumb,'),1}']); end try outdata = eval(equation); % Setting the output signal name: ifsetName = get_param(currparent,'UserData'); if ~isempty(ifsetName) && isa(ifsetName,'char') % ifsetName = ifsetName; else ifsetName = get_param(currparent,'Name'); end if numel(outdata)==1 outdata = setName(outdata,ifsetName); else for i=1:size(outdata,1) for j=1:size(outdata,2) outdata(i,j) = setName(outdata(i,j),[ifsetName,'_',num2str(i),'-',num2str(j)]); end end end x = size(LTPDAinvar,1); blockName = currparent; for i=1:numel(blockName), if double(blockName(i))==10, blockName(i)=' '; end; end LTPDAinvar = [LTPDAinvar;{outdata,0,blockName}]; block.OutputPort(1).Data = x+1; probe = get_param(currparent,'MaskHelp'); if ~isempty(probe) && isa(probe,'char') && strcmp(probe,'probe') LTPDAinvar{size(LTPDAinvar,1),2} = 2; end return catch err disp(sprintf('Something''s wrong in the calculation of the results of the ''%s'' arithmetic block.',get_param(currparent,'Name'))) disp('The inputs were:') for i=1:nparams(params) disp(['Input ',num2str(i),':']) LTPDAinvar{block.InputPort(1).Data(i),1} %#ok<NOPRT> end disp('The equation was:') disp(eq) close(findobj('Name','LTPDA Progress Bar')) rethrow(err) end end % for the arithmetic block % ======================================================================== %% =================== RETRIEVE THE PARAMETERS LIST ====================== % ======================================================================== % The command line to produce the proper parameters list for the block % currently executed is retrieved from the description of this parent subsystem paramcommand = get_param(subsyshandle,'Description'); loopExecution = 0; if ~isempty(paramcommand) eval(paramcommand); % Verify if a global variable or nested loop variable has been used: for i=1:nparams(params) currVal = params.params(i).val; if ischar(currVal) && numel(currVal)>5 && strcmp(currVal(1:5),'loop.') loopExecution = 1; try %#ok<ALIGN> setVal(params.params(i),eval(params.params(i).val)); catch, end end if ischar(currVal) && numel(currVal)>3 && strcmp(currVal(1:3),'gl.') try %#ok<ALIGN> setVal(params.params(i),eval(params.params(i).val)); catch, end end end if ~exist('paramEnabled','var'), paramEnabled = ones(1,nparams(params)); end currparam = plist(); for jj=1:nparams(params) if paramEnabled(jj)==1 if numel(params.params(jj).key)>6 && strcmpi(params.params(jj).key(1:7),'addPar_'), params.params(jj).setKey(params.params(jj).key(8:end)); end currparam = append(currparam,params.params(jj)); end end else currparam = plist(); end % Retrieve parameters from Simulink: paramFromSimulink = 0; for i=1:nparams(currparam) paramKey2 = currparam.params(i).key; if numel(paramKey2)>7 && strcmpi(paramKey2(1:7),'addPar_'), paramKey = paramKey2(8:end); else paramKey = paramKey2; end paramVal = currparam.params(i).val; if (isa(paramVal,'char') && strcmp(paramVal,'-->')) || (isa(paramVal,'cell') && numel(paramVal)==1 && isa(paramVal{1},'char') && strcmp(paramVal{1},'-->')) paramFromSimulink = paramFromSimulink + 1; mux = find_system(currparent,'SearchDepth',1,'LookUnderMasks','all','BlockType','Mux'); muxWidths = get_param(mux{1},'CompiledPortWidths'); muxWidths = muxWidths.Inport; inputBlock = find_system(currparent,'SearchDepth',1,'LookUnderMasks','all','Name',lower(paramKey)); if numel(inputBlock)>1, inputBlock(1)=[]; end % this can happen only when the currparent has the same name: then, ignore the 1st, ie. the currparent itself inputNumb = str2double(get_param(inputBlock{1},'Tag')); x = 0; for j=1:inputNumb-1 x=x+muxWidths(j); end paramVal = [LTPDAinvar{block.InputPort(1).Data(x+1)}]; if muxWidths(inputNumb)>1 for j=x+2:x+muxWidths(inputNumb) paramVal = [paramVal,LTPDAinvar{block.InputPort(1).Data(j)}]; end end currparam = pset(currparam,paramKey2,paramVal); end end % ======================================================================== %% ======================== CALCULATE THE RESULTS ========================= % ======================================================================== y = length(block.InputPort(1).Data) - paramFromSimulink; % Check to verify the type of function: specFunc = {'display'}; [meth,clas] = strtok(get(get_param(currparent,'Handle'),'Tag')); category = ''; if strcmp(meth,'method') clas = strtrim(clas); infoObj = eval([clas,'.getInfo(''',blocktag,''')']); category = infoObj.mcategory; end if ismember(blocktag,specFunc) % Input, but no parameters and no output type = 4; % ====================================== elseif strcmp(category,'Output') % Input and parameters, but no output type = 3; % =================================== elseif ~isempty(utils.prog.find_in_models(currparent,'SearchDepth',1,'LookUnderMasks','all','BlockType','Ground')) || block.InputPort(1).Data(1)==0 % No input, but parameters and output type = 2; % =================================== elseif nparams(currparam)==0 % Input and output, but no parameters type = 1; % ============================ else % Input, parameters and output type = 0; % ============================ end switch type % ==================================================================== case 4 % Input, but no parameters and no output command = 'feval(blocktag,'; for i=1:y dVal = block.InputPort(1).Data(i); if dVal>0, command = [command sprintf('LTPDAinvar{%d},', dVal)]; end end command = [command(1:end-1) ');']; try eval(command) catch err disp('4') disp(sprintf('Something''s wrong in the calculation of the results of the %s function.',blocktag)) disp(sprintf('The name of the currently executed block is %s.',get_param(currparent,'Name'))) disp(sprintf('The (first) input data ordinal number, in the list of objects, was %d.',block.InputPort(1).Data(1))) close(findobj('Name','LTPDA Progress Bar')) rethrow(err) end block.OutputPort(1).Data = 1; % this will be ignored: no output expected. return; % ==================================================================== case 3 % Input and parameters, but no output try command = 'feval(blocktag,'; for i=1:y dVal = block.InputPort(1).Data(i); if dVal>0, command = [command sprintf('LTPDAinvar{%d},', dVal)]; end end command = [command 'currparam);']; if strcmpi(blocktag,'plot'), figure; end; eval(command); catch err disp('3') disp(sprintf('Something''s wrong in the calculation of the results of the %s function.',blocktag)) disp(sprintf('The name of the currently executed block is %s.',get_param(currparent,'Name'))) disp(sprintf('The (first) input data ordinal number, in the list of objects, was %d.',block.InputPort(1).Data(1))) disp('The plist passed was:') currparam %#ok<NOPRT> close(findobj('Name','LTPDA Progress Bar')) rethrow(err) end block.OutputPort(1).Data = 1; % this will be ignored: no output expected. return; % ==================================================================== case 2 % No input, but parameters and output try outdata = feval(blocktag,currparam); catch err disp('2') disp(sprintf('Something''s wrong in the calculation of the results of the %s function.',blocktag)) disp(sprintf('The name of the currently executed block is %s.',get_param(currparent,'Name'))) disp('The plist passed was:') currparam %#ok<NOPRT> close(findobj('Name','LTPDA Progress Bar')) rethrow(err) end % ==================================================================== case 1 % Input and output, but no parameters try command = 'outdata = feval(blocktag,'; for i=1:y dVal = block.InputPort(1).Data(i); if dVal>0, command = [command sprintf('LTPDAinvar{%d},', dVal)]; end end command = [command(1:end-1) ');']; eval(command); catch err disp('1') disp(sprintf('Something''s wrong in the calculation of the results of the %s function.',blocktag)) disp(sprintf('The name of the currently executed block is %s.',get_param(currparent,'Name'))) disp(sprintf('The (first) input data ordinal number, in the list of objects, was %d.',block.InputPort(1).Data(1))) disp('The plist passed was:') currparam %#ok<NOPRT> close(findobj('Name','LTPDA Progress Bar')) rethrow(err) end % ==================================================================== case 0 % Input, parameters and output try command = 'outdata = feval(blocktag,'; for i=1:y dVal = block.InputPort(1).Data(i); if dVal>0, command = [command sprintf('LTPDAinvar{%d},', dVal)]; end end command = [command 'currparam);']; eval(command); catch err disp('1') disp(sprintf('Something''s wrong in the calculation of the results of the %s function.',blocktag)) disp(sprintf('The name of the currently executed block is %s.',get_param(currparent,'Name'))) disp(sprintf('The (first) input data ordinal number, in the list of objects, was %d.',block.InputPort(1).Data(1))) disp('The plist passed was:') currparam %#ok<NOPRT> close(findobj('Name','LTPDA Progress Bar')) rethrow(err) end end %========================================================================== %% Cycle to remove objects from memory as soon as they're no longer necessary: %========================================================================== if ~getappdata(0,'maintainresults'); portConnectivity = get(subsyshandle,'PortConnectivity'); for i = 1:numel(portConnectivity) notUsedAnymore = 1; if isempty(portConnectivity(i).DstBlock) parentBlock = portConnectivity(i).SrcBlock; childrenBlocks = utils.prog.findchildren(parentBlock); for j = 1:numel(childrenBlocks) if isempty(get_param(childrenBlocks(j),'MaskVariables')), notUsedAnymore = 0; end end % disp(sprintf('*** (Currently executing block %s)',get_param(currparent,'Name'))) if notUsedAnymore && LTPDAinvar{block.InputPort(1).Data(i),2}==0 % disp(['*** Removed object n°.',num2str(block.InputPort(1).Data(i)),', which was a ',class(LTPDAinvar{block.InputPort(1).Data(i),1}),'.']) disp(sprintf('*** (Currently executing block %s)',get_param(currparent,'Name'))) LTPDAinvar(block.InputPort(1).Data(i),:) = []; % Update the execution history: ltpda_annotation = find_system(bdroot,'FindAll','on','Type','Annotation','Tag','ltpda model'); execHistory = get_param(ltpda_annotation,'UserData'); for xx=1:size(execHistory,1) for yy=3:size(execHistory,2), if execHistory{xx,yy} == block.InputPort(1).Data(i), execHistory{xx,yy} = -1; end if execHistory{xx,yy} > block.InputPort(1).Data(i), execHistory{xx,yy} = execHistory{xx,yy}-1; end end if execHistory{xx,1} == block.InputPort(1).Data(i), execHistory{xx,1} = -1; end if execHistory{xx,1} > block.InputPort(1).Data(i), execHistory{xx,1} = execHistory{xx,1}-1; end end set_param(ltpda_annotation,'UserData',execHistory); disp('*** LTPDA object cleared from memory, being now unused') end end end end % ======================================================================== %% =============================== OUTPUTS ================================ % ======================================================================== % Set this block status to 'executed': set(subsyshandle,'MaskVariables','1'); set(gcbh,'MaskVariables','1'); signalName = get_param(currparent,'Name'); ifsetName = get_param(currparent,'UserData'); if ~isempty(ifsetName) && isa(ifsetName,'double') && ifsetName==1 if numel(outdata)==1 outdata = setName(outdata,signalName); else for i=1:size(outdata,1) for j=1:size(outdata,2) outdata(i,j) = set(outdata(i,j),'name',[signalName,'_',num2str(i),'-',num2str(j)]); end end end end try % To prevent the result calculated here from being canceled at the % end of the calculation: probe = get_param(currparent,'MaskHelp'); if ~isempty(probe) && isa(probe,'char') && strcmp(probe,'probe'), keepThis = 1; else keepThis = 0; end % Appending the results: ltpda_annotation = find_system(bdroot,'FindAll','on','Type','Annotation','Tag','ltpda model'); execHistory = get_param(ltpda_annotation,'UserData'); % If there's a previous execution history, check if the current block belongs to it: if ~isempty(execHistory) member = 0; for i=1:size(execHistory,1) if execHistory{i,2}==subsyshandle, member = 1; index = i; break; end end end if ~isempty(execHistory) && member && ~loopExecution x = execHistory{index,1}; if x==-1, x = size(LTPDAinvar,1)+1; end for i=1:numel(currparent), if double(currparent(i))==10, currparent(i)=' '; end; end LTPDAinvar(x,:) = {outdata,keepThis,currparent}; block.OutputPort(1).Data = x; execHistory{index,1} = x ; execHistory{index,2} = subsyshandle ; for i=1:y , execHistory{index,2+i} = block.InputPort(1).Data(i); end else if isempty(execHistory), execHistory = {}; end x = size(LTPDAinvar,1); LTPDAinvar = [LTPDAinvar;{outdata,keepThis,currparent}]; block.OutputPort(1).Data = x+1; execHistory{end+1,1} = x+1 ; execHistory{end,2} = subsyshandle ; for i=1:y , execHistory{end,2+i} = block.InputPort(1).Data(i); end end % Update the execution history: % Are stored the the output obj pointer, the handle of the current subsytem and the input obj pointers: set_param(ltpda_annotation,'UserData',execHistory); catch disp('------------------============================================------------------') disp('------------------============================================------------------') disp('------------------============================================------------------') disp(sprintf('Something''s wrong in appending to the global variable LTPDAinvar the results of the %s function.',blocktag)) disp(sprintf('The name of the currently executed block is %s.',get_param(currparent,'Name'))) disp('The data to be saved, calculated into this block, are:') outdata %#ok<NOPRT> disp('------------------============================================------------------') disp('------------------============================================------------------') disp('------------------============================================------------------') end %========================================================================== % The output to Simulink is just the ordinal number (ONE AND ONLY ONE % NUMBER) of the object appended to the global array LTPDAinvar. % endfunction