├── imgs
├── Cover.png
└── SocialPreview.png
├── doc
├── figs
│ ├── Demo.png
│ ├── GUI.png
│ ├── Demo1a.png
│ ├── Demo1b.png
│ ├── Demo2.png
│ ├── Module.pdf
│ ├── Interface.png
│ ├── ContextMenu1.png
│ ├── ContextMenu2.png
│ ├── ContextMenu3.png
│ ├── McSCert_Logo.pdf
│ ├── GuidelineSelector.png
│ └── FunctionVisibilityParam.png
├── SimulinkModule_UserGuide.pdf
└── tex
│ ├── macros.tex
│ └── SimulinkModule_UserGuide.tex
├── src
├── Interface
│ ├── Iterator
│ │ ├── Iterator.m
│ │ └── license.txt
│ ├── InterfaceHeader.m
│ ├── dependencies.m
│ ├── InterfaceIterator.m
│ ├── getSampleTime.m
│ ├── getDataType_MJ.m
│ ├── getDimensions.m
│ ├── InterfaceItem.m
│ └── Interface.m
├── Guidelines
│ ├── guidelineSelector.fig
│ ├── guideline0001.m
│ ├── guideline0002.m
│ ├── guideline0004.m
│ ├── guideline0003.m
│ └── guidelineSelector.m
├── isSubsystem.m
├── isLibraryLink.m
├── inAtomicSubsystem.m
├── reqSimFcnName.m
├── isGoodSimFcnName.m
├── isGlobalDataStore.m
├── subToSimFcn.m
└── sl_customization.m
├── .gitignore
├── .gitmodules
├── README.md
├── LICENSE
└── example
└── Demo.mdl
/imgs/Cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/McSCert/Simulink-Module/HEAD/imgs/Cover.png
--------------------------------------------------------------------------------
/doc/figs/Demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/McSCert/Simulink-Module/HEAD/doc/figs/Demo.png
--------------------------------------------------------------------------------
/doc/figs/GUI.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/McSCert/Simulink-Module/HEAD/doc/figs/GUI.png
--------------------------------------------------------------------------------
/doc/figs/Demo1a.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/McSCert/Simulink-Module/HEAD/doc/figs/Demo1a.png
--------------------------------------------------------------------------------
/doc/figs/Demo1b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/McSCert/Simulink-Module/HEAD/doc/figs/Demo1b.png
--------------------------------------------------------------------------------
/doc/figs/Demo2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/McSCert/Simulink-Module/HEAD/doc/figs/Demo2.png
--------------------------------------------------------------------------------
/doc/figs/Module.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/McSCert/Simulink-Module/HEAD/doc/figs/Module.pdf
--------------------------------------------------------------------------------
/doc/figs/Interface.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/McSCert/Simulink-Module/HEAD/doc/figs/Interface.png
--------------------------------------------------------------------------------
/imgs/SocialPreview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/McSCert/Simulink-Module/HEAD/imgs/SocialPreview.png
--------------------------------------------------------------------------------
/doc/figs/ContextMenu1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/McSCert/Simulink-Module/HEAD/doc/figs/ContextMenu1.png
--------------------------------------------------------------------------------
/doc/figs/ContextMenu2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/McSCert/Simulink-Module/HEAD/doc/figs/ContextMenu2.png
--------------------------------------------------------------------------------
/doc/figs/ContextMenu3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/McSCert/Simulink-Module/HEAD/doc/figs/ContextMenu3.png
--------------------------------------------------------------------------------
/doc/figs/McSCert_Logo.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/McSCert/Simulink-Module/HEAD/doc/figs/McSCert_Logo.pdf
--------------------------------------------------------------------------------
/doc/SimulinkModule_UserGuide.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/McSCert/Simulink-Module/HEAD/doc/SimulinkModule_UserGuide.pdf
--------------------------------------------------------------------------------
/doc/figs/GuidelineSelector.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/McSCert/Simulink-Module/HEAD/doc/figs/GuidelineSelector.png
--------------------------------------------------------------------------------
/src/Interface/Iterator/Iterator.m:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/McSCert/Simulink-Module/HEAD/src/Interface/Iterator/Iterator.m
--------------------------------------------------------------------------------
/doc/figs/FunctionVisibilityParam.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/McSCert/Simulink-Module/HEAD/doc/figs/FunctionVisibilityParam.png
--------------------------------------------------------------------------------
/src/Guidelines/guidelineSelector.fig:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/McSCert/Simulink-Module/HEAD/src/Guidelines/guidelineSelector.fig
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | doc/tex/SimulinkModule_UserGuide.aux
3 | doc/tex/SimulinkModule_UserGuide.log
4 | doc/tex/SimulinkModule_UserGuide.out
5 | doc/tex/SimulinkModule_UserGuide.synctex.gz
6 | doc/tex/SimulinkModule_UserGuide.toc
7 | *.asv
8 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "src/Utility"]
2 | path = src/Utility
3 | url = https://github.com/McSCert/Simulink-Utility.git
4 | [submodule "src/LineToGotoFrom"]
5 | path = src/LineToGotoFrom
6 | url = https://github.com/McSCert/LineToGotoFrom.git
7 |
--------------------------------------------------------------------------------
/src/isSubsystem.m:
--------------------------------------------------------------------------------
1 | function b = isSubsystem(blocks)
2 | % ISSUBSYSTEM Determine if the block is a subsystem.
3 | %
4 | % Inputs:
5 | % block Pathname or handle of a block.
6 | %
7 | % Outputs:
8 | % b Whether the block is a subsystem(1) or not(0).
9 |
10 | % Convert the input to handles
11 | blocks = inputToNumeric(blocks);
12 |
13 | b = zeros(1, length(blocks));
14 | % Check each block to see if its a subsystem
15 | for block = 1:length(blocks)
16 | try
17 | blockType = get_param(blocks(block), 'BlockType');
18 | b(block) = strcmpi(blockType, 'SubSystem');
19 | catch % Unexpected error
20 | end
21 | end
22 | end
--------------------------------------------------------------------------------
/src/isLibraryLink.m:
--------------------------------------------------------------------------------
1 | function b = isLibraryLink(blocks)
2 | % ISLIBRARYLINK Determines if the block is a link to a library.
3 | %
4 | % Inputs:
5 | % block Pathname or handle of a block.
6 | %
7 | % Outputs:
8 | % b Whether the block is a Library Link(1) or not(0).
9 |
10 | % Convert whatever input to handles
11 | blocks = inputToNumeric(blocks);
12 |
13 | b = zeros(1, length(blocks));
14 |
15 | % Check if block is a Library Link
16 | for i = 1:length(blocks)
17 | try
18 | b(i) = strcmpi(get_param(blocks(i), 'LinkStatus'), 'resolved') && ...
19 | ~isempty(get_param(blocks(i), 'ReferenceBlock'));
20 | catch % block does not have this parameter
21 | end
22 | end
23 | end
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Simulink Module Tool
2 | [](https://doi.org/10.5281/zenodo.4321692)
3 | [](https://www.mathworks.com/matlabcentral/fileexchange/71952-simulink-module-tool)
4 |
5 | The Simulink Module Tool performs several functions in order to support modular development for Simulink models:
6 |
7 | * Scoping Simulink Functions
8 | * Creating pre-configured Function callers
9 | * Converting SubSystems into Simulink Functions
10 | * Visualizing or printing a syntactic interface
11 | * Listing module dependencies
12 | * Checking guidelines
13 |
14 |
15 |
16 | ## User Guide
17 | For installation and other information, please see the [User Guide](doc/SimulinkModule_UserGuide.pdf).
18 |
--------------------------------------------------------------------------------
/src/inAtomicSubsystem.m:
--------------------------------------------------------------------------------
1 | function [isAtomic, sysAtomic] = inAtomicSubsystem(block)
2 | % ISATOMICSUBSYSTEM Determine if the block is contained in an atomic subsystem.
3 | %
4 | % Inputs:
5 | % block Block name.
6 | %
7 | % Outputs:
8 | % isAtomic Whether the block resides in an atomic subsystem(1) or not(0).
9 | % sysAtomic Atomic subsystem in which the block resides.
10 |
11 | isAtomic = false;
12 | sysAtomic = '';
13 |
14 | parent = get_param(block, 'Parent');
15 | while ~isempty(parent)
16 | disp(parent)
17 | try
18 | isAtomic = strcmpi(get_param(parent, 'TreatAsAtomicUnit'), 'on');
19 | if isAtomic
20 | sysAtomic = parent;
21 | return;
22 | end
23 | parent = get_param(parent, 'Parent');
24 | catch ME
25 | % reached root
26 | if strcmpi(ME.identifier, 'Simulink:Commands:ParamUnknown')
27 | return;
28 | end
29 | end
30 | end
31 | end
--------------------------------------------------------------------------------
/src/Interface/InterfaceHeader.m:
--------------------------------------------------------------------------------
1 | classdef InterfaceHeader
2 | % INTERFACEHEADER The headers used in displaying an interface.
3 | properties
4 | Label % Label text.
5 | Handle % Handle of the annotation.
6 | end
7 | methods (Access = public)
8 | function obj = InterfaceHeader(label)
9 | obj.Label = label;
10 | end
11 | function obj = delete(obj)
12 | % DELETE Delete the header from the model.
13 | %
14 | % Inputs:
15 | obj = obj.update;
16 | try
17 | delete(obj.Handle);
18 | catch ME
19 | if ~strcmp(ME.identifier, 'MATLAB:hg:udd_interface:CannotDelete')
20 | rethrow(ME)
21 | end
22 | end
23 | obj.Handle = [];
24 | end
25 | function obj = update(obj)
26 |
27 | if isempty(obj.Handle)
28 | return
29 | end
30 |
31 | sys = bdroot(gcs);
32 | path = [sys '/' obj.Label];
33 | obj.Handle = get_param(path, 'Handle');
34 | end
35 | end
36 | end
--------------------------------------------------------------------------------
/src/reqSimFcnName.m:
--------------------------------------------------------------------------------
1 | function simulinkFcnName = reqSimFcnName()
2 | % REQSIMFCNNAME Prompt the user to input a Simulink Function name until a
3 | % name is entered which is not the same as another Simulink Function in scope.
4 | %
5 | % Inputs:
6 | % N/A
7 | %
8 | % Outputs:
9 | % simulinkFcnName Char array representing a Simulink Function name.
10 | %
11 | % Example:
12 | % simulinkFcnName = getSimFcnName()
13 | %
14 | % ans = 'Function_Name'
15 |
16 | %% Dialog Box Parameters
17 | prompt = 'Enter a name for the Simulink Function: ';
18 | dlgtitle = 'Convert Subsystem';
19 | dims = [1 50];
20 | definput = {'f'};
21 |
22 | %% Checking Input
23 | % Loop until the input name is acceptable
24 | while 1
25 | inputName = inputdlg(prompt, dlgtitle, dims, definput);
26 | % Check to see if the name shadows other names in scope
27 | if isGoodSimFcnName(gcs, inputName{1})
28 | break
29 | else
30 | waitfor(msgbox([inputName{1}, ...
31 | ' is already used as a Simulink Function in scope.', ...
32 | char(10), 'Please enter a new name.'], dlgtitle));
33 | end
34 | end
35 | simulinkFcnName = inputName{1};
36 | end
--------------------------------------------------------------------------------
/src/isGoodSimFcnName.m:
--------------------------------------------------------------------------------
1 | function goodName = isGoodSimFcnName(subsystem, simulinkFcnName)
2 | % ISGOODSIMFCNNAME Check if a Simulink Function name is the same as any other
3 | % Simulink Functions in scope at the current subsystem level.
4 | %
5 | % Inputs:
6 | % subsystem Path of a subsystem where a Simulink Function will be added.
7 | % simulinkFcnName Name of the Simulink Function to be added.
8 | %
9 | % Outputs:
10 | % goodName Whether the name can be used(1) or not(0).
11 | %
12 | % Example:
13 | % isGoodSimFcnName('SubSystem_Name', 'SimFcnName')
14 | %
15 | % ans = 1
16 |
17 | % Get callable Simulink Functions at the current scope
18 | [~, prototype] = getCallableFunctions(subsystem);
19 |
20 | % Get the prototype names
21 | prototypeNames = getPrototypeName(prototype);
22 |
23 | % Make sure the prototype name is a cell
24 | if ~iscell(prototypeNames)
25 | prototypeNames = {prototypeNames};
26 | end
27 |
28 | result = zeros(1, length(prototypeNames));
29 |
30 | % Loop through each prototype name
31 | for name = 1:length(prototypeNames)
32 | % Compare to the input name
33 | result(name) = ~strcmp(simulinkFcnName, prototypeNames{name});
34 | end
35 | % Return true if none of the prototype names are the same as the input name
36 | goodName = all(result);
37 | end
--------------------------------------------------------------------------------
/src/Guidelines/guideline0001.m:
--------------------------------------------------------------------------------
1 | function [blocks, location] = guideline0001(model)
2 | % GUIDELINE0001 Check that a model complies to Guideline 1. Return blocks
3 | % that are not in compliance. Blocks are not in compliance if they are not
4 | % placed in the lowest possible hierarchical position that is a common parent
5 | % amoung its callers.
6 | %
7 | % Inputs:
8 | % model Simulink model name.
9 | %
10 | % Outputs:
11 | % blocks Simulink Function block fullnames.
12 | % location Proposed correct location.
13 |
14 | % Get the model
15 | try
16 | model = bdroot(model);
17 | catch % not loaded
18 | error(['Model ''' model ''' is not loaded.']);
19 | end
20 |
21 | fcns = find_system(model, 'BlockType', 'SubSystem');
22 | fcns = fcns(isSimulinkFcn(fcns) == 1);
23 | currentLocation = get_param(fcns, 'Parent');
24 |
25 | blocks = {};
26 | location = {};
27 |
28 | for i = 1:length(fcns)
29 | % Find corresponding Function callers
30 | callers = findCallers(fcns{i});
31 | if isempty(callers)
32 | continue
33 | end
34 | % Find lowest common parent of callers
35 | idealLocation = commonParents(callers);
36 |
37 | % If subsystem is not placed in this spot, it can be placed lower or higher
38 | % than its current position
39 | if ~strcmp(idealLocation, currentLocation{i})
40 | blocks{end+1} = fcns{i};
41 | location{end+1} = idealLocation;
42 | end
43 | end
44 | end
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2022, McSCert
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | 2. Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | 3. Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/src/Guidelines/guideline0002.m:
--------------------------------------------------------------------------------
1 | function blocks = guideline0002(model)
2 | % GUIDELINE0002 Check that a model complies to Guideline 2. Return blocks
3 | % that are not in compliance. Blocks are not in compliance if they have global
4 | % visibility, and are not used outside of the model. It is not possible to
5 | % check is all models (loaded and unloaded) use the function, which would
6 | % justify the global visibility. Therefore, we err on the side of caution, and
7 | % return all blocks with global visibility.
8 | %
9 | % Inputs:
10 | % model Simulink model name.
11 | %
12 | % Outputs:
13 | % blocks Simulink Function block names.
14 |
15 | blocks = find_system(model, 'BlockType', 'SubSystem');
16 | blocks = blocks(isSimulinkFcn(blocks) == 1);
17 |
18 | visibility = cell(size(blocks));
19 |
20 | for i = 1:length(blocks)
21 | % 1) Get Function Visibility parameter
22 | triggerPort = find_system(blocks{i}, 'SearchDepth', 1, 'FollowLinks', 'on', ...
23 | 'BlockType', 'TriggerPort', ...
24 | 'TriggerType', 'function-call');
25 | try
26 | visibility{i} = get_param(triggerPort{1}, 'FunctionVisibility');
27 | catch
28 | % Either not a Simulink Function, or earlier versions of
29 | % Simulink Functions (e.g. 2014b) do not have this parameter
30 | visibility{i} = '';
31 | continue
32 | end
33 | end
34 |
35 | globalVisibility = strcmp(visibility, 'global') == 1;
36 | blocks = blocks(globalVisibility);
37 | end
--------------------------------------------------------------------------------
/src/Guidelines/guideline0004.m:
--------------------------------------------------------------------------------
1 | function blocks = guideline0004(model)
2 | % GUIDELINE0004 Check that a model complies to Guideline 4. Return blocks
3 | % that are not in compliance. Blocks are not in compliance if they interact
4 | % with the base workspace (e.g., To Workspace, From File, etc.)
5 | %
6 | % Inputs:
7 | % model Simulink model name.
8 | %
9 | % Outputs:
10 | % blocks Block fullnames.
11 |
12 | % Get the model
13 | try
14 | model = bdroot(model);
15 | catch % not loaded
16 | error(['Model ''' model ''' is not loaded.']);
17 | end
18 |
19 | ff = find_system(model, 'BlockType', 'FromFile', 'Commented', 'off');
20 | fs = find_system(model, 'BlockType', 'FromSpreadsheet', 'Commented', 'off');
21 | fw = find_system(model, 'BlockType', 'FromWorkspace', 'Commented', 'off');
22 | tf = find_system(model, 'BlockType', 'ToFile', 'Commented', 'off');
23 | tw = find_system(model, 'BlockType', 'ToWorkspace', 'Commented', 'off');
24 |
25 | % Global data stores in the base workspace are not be allowed.
26 | % Data Dictionary and model workspace are OK.
27 | dswr = [find_system(model, 'BlockType', 'DataStoreWrite', 'Commented', 'off'); ...
28 | find_system(model, 'BlockType', 'DataStoreRead', 'Commented', 'off');];
29 | ds = {};
30 | for i = 1:length(dswr)
31 | [isGlobal, ~, location] = isGlobalDataStore(dswr{i});
32 | if isGlobal && strcmp(location, 'base')
33 | ds{end+1,1} = dswr{i};
34 | end
35 | end
36 |
37 | blocks = vertcat(ff, fs, fw, tf, tw, ds);
38 | end
--------------------------------------------------------------------------------
/src/Interface/Iterator/license.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2009-2010, The MathWorks, Inc.
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are
6 | met:
7 |
8 | * Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | * Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in
12 | the documentation and/or other materials provided with the distribution.
13 | * In all cases, the software is, and all modifications and derivatives
14 | of the software shall be, licensed to you solely for use in conjunction
15 | with MathWorks products and service offerings.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 | POSSIBILITY OF SUCH DAMAGE.
28 |
--------------------------------------------------------------------------------
/src/Interface/dependencies.m:
--------------------------------------------------------------------------------
1 | function dependencies(sys)
2 | % DEPENDENCIES List the model dependencies in the Command Window.
3 | %
4 | % Inputs:
5 | % sys Model model
6 | %
7 | % Outputs:
8 | % N/A
9 |
10 | sys = bdroot(sys);
11 |
12 | % Initialize counts
13 | mr_n = 0;
14 | ll_n = 0;
15 | dd_n = 0;
16 |
17 | %% 1) Model References
18 | mr = find_system(sys, 'BlockType', 'ModelReference', 'Commented', 'off');
19 | % Remove non-unique based on ModelFile
20 | modelname = get_param(mr, 'ModelFile');
21 | [~, idx] = unique(modelname);
22 | mr = mr(idx);
23 | if isempty(mr)
24 | mr = {'N/A'};
25 | else
26 | mr = replaceNewline(mr);
27 | mr_n = length(mr);
28 | end
29 |
30 | %% 2) Linked Library Blocks
31 | ll = find_system(sys, 'FollowLinks', 'on', 'LinkStatus', 'resolved', 'Commented', 'off');
32 | % In case sys is a library, remove any dependencies to itself
33 | lib = bdroot(ll);
34 | idx = ~strcmp(lib, sys);
35 | ll = ll(idx);
36 | if isempty(ll)
37 | ll = {'N/A'};
38 | else
39 | ll = replaceNewline(ll);
40 | ll_n = length(ll);
41 | end
42 |
43 | %% 3) Data Dictionary
44 | try
45 | dd = get_param(sys, 'DataDictionary');
46 | if isempty(dd)
47 | dd = 'N/A';
48 | else
49 | dd = replaceNewline(dd);
50 | dd_n = length(dd);
51 | end
52 | catch % Parameter does not exist in earlier versions
53 | dd = 'N/A';
54 | end
55 |
56 | %% Print
57 | fprintf('Model References (%d)\n', mr_n);
58 | fprintf('------\n');
59 | for i = 1:length(mr)
60 | fprintf('%s\n', mr{i});
61 | end
62 |
63 | fprintf('\nLibrary Links (%d)\n', ll_n);
64 | fprintf('------\n');
65 | for i = 1:length(ll)
66 | fprintf('%s\n', ll{i});
67 | end
68 |
69 | fprintf('\nData Dictionaries (%d)\n', dd_n);
70 | fprintf('------\n');
71 | fprintf('%s\n', dd);
72 | end
--------------------------------------------------------------------------------
/src/Guidelines/guideline0003.m:
--------------------------------------------------------------------------------
1 | function [blocks, shadows] = guideline0003(model)
2 | % GUIDELINE003 Check that a model complies to Guideline 3. Return blocks
3 | % that are not in compliance. Blocks are not in compliance if they are in the
4 | % scope of one or more function blocks with the same name and parameters.
5 | %
6 | % Inputs:
7 | % model Simulink model name.
8 | %
9 | % Outputs:
10 | % blocks Simulink Function block fullnames.
11 | % shadows Simulink Function block fullnames.
12 |
13 | % Get the model
14 | try
15 | model = bdroot(model);
16 | catch % not loaded
17 | error(['Model ''' model ''' is not loaded.']);
18 | end
19 |
20 | fcns = find_system(model, 'BlockType', 'SubSystem');
21 | fcns = fcns(isSimulinkFcn(fcns) == 1);
22 |
23 | blocks = {};
24 | shadows = {};
25 |
26 | % Note:
27 | % - Functions with the same name in same subsystem (Error)
28 | % - Two global functions with same name in different subsystems (Error)
29 |
30 | for i = 1:length(fcns)
31 | % Get all Simulink functions that are in scope
32 | [inscopeFcns, inscopePrototyes] = getCallableFunctions(get_param(fcns{i}, 'Parent'));
33 |
34 | % Remove itself
35 | i_idx = find(strcmp(inscopeFcns, fcns{i}));
36 | inscopeFcns(i_idx) = '';
37 | inscopePrototyes(i_idx) = '';
38 |
39 | % Get function names
40 | %inscopeNames = getPrototypeName(inscopePrototyes);
41 | %n = getPrototypeName(getPrototype(fcns{i}));
42 |
43 | % Check if there are any function prototype that are the same
44 | found = strfind(inscopePrototyes, getPrototype(fcns{i}));
45 | if ~iscell(found)
46 | found = {found};
47 | end
48 | idx = find(not(cellfun('isempty', found)));
49 | if ~isempty(idx) % If yes, add to list of shadowing functions
50 | blocks{end+1} = fcns{i};
51 | shadows{end+1} = inscopeFcns(idx);
52 | end
53 | end
54 | end
55 |
--------------------------------------------------------------------------------
/src/Interface/InterfaceIterator.m:
--------------------------------------------------------------------------------
1 | classdef InterfaceIterator < Iterator
2 |
3 | properties(Access = private)
4 | loc; % Current location of traversal.
5 | end
6 |
7 | methods
8 | function newObj = InterfaceIterator(varargin)
9 | narginchk(0,1);
10 |
11 | if nargin == 0
12 | % Store reference to empty interface and position iterator at start.
13 | newObj.collection = Interface();
14 | newObj.loc = 1;
15 | else
16 | % Store reference to interface and position iterator at start.
17 | newObj.collection = varargin{1};
18 | newObj.loc = 1;
19 | end
20 | end
21 |
22 | % Concrete implementation. See Iterator superclass.
23 | function el = next(obj)
24 | % NEXT Advance to the next element in sequence in the collection and
25 | % return it.
26 | %
27 | % Inputs:
28 | % obj InterfaceIterator object.
29 | %
30 | % Outputs:
31 | % el Next element in the interface.
32 |
33 | if obj.hasNext()
34 | el = obj.collection.get(obj.loc);
35 | obj.loc = obj.loc + 1;
36 | end
37 | end
38 |
39 | % Concrete implementation. See Iterator superclass.
40 | function next = hasNext(obj)
41 | % HASBEXT Check if the there is another element in the traversal of the
42 | % collection.
43 | %
44 | % Inputs:
45 | % obj InterfaceIterator object.
46 | %
47 | % Outputs:
48 | % next Whether the is another interface element next (1), or
49 | % not (0);
50 |
51 | next = obj.loc <= obj.collection.length();
52 | end
53 |
54 | % Concrete implementation. See Iterator superclass.
55 | function reset(obj)
56 | % RESET Position iterator at the start.
57 | %
58 | % Inputs:
59 | % obj InterfaceIterator object.
60 | %
61 | % Outputs:
62 | % N/A
63 |
64 | obj.loc = 1;
65 | end
66 | end
67 | end
68 |
--------------------------------------------------------------------------------
/src/Interface/getSampleTime.m:
--------------------------------------------------------------------------------
1 | function time = getSampleTime(block)
2 | % GETSAMPLETIME Determine the block sample time. Based on the
3 | % SampleTime and CompiledSampleTime parameters. Note that some blocks may have
4 | % different sample rates for different ports (e.g. SubSystems containing blocks
5 | % with different rates). Sample time may be more accurate after model
6 | % compilation.
7 | %
8 | % Inputs:
9 | % block Block path or handle.
10 | %
11 | % Outputs:
12 | % time Vector of sample times.
13 | %
14 | % Example:
15 | % >> getSampleTime('ex_compiled_sample_new/Sine Wave3')
16 | % ans =
17 | % 0.5000
18 | %
19 | % >> getSampleTime('ex_compiled_sample_new/Atomic Subsystem')
20 | % ans =
21 | % 3
22 | % 4
23 | %
24 | % See: www.mathworks.com/help/simulink/ug/determining-the-compiled-sample-time-of-a-block.html
25 | % See: https://www.mathworks.com/help/simulink/ug/types-of-sample-time.html
26 |
27 | narginchk(1,1);
28 |
29 | % 1) Get the SampleTime
30 | sampleTime = [];
31 | try
32 | sampleTime = str2double(get_param(block, 'SampleTime'));
33 | catch ME
34 | if ~strcmpi(ME.identifier, 'Simulink:Commands:ParamUnknown')
35 | rethrow(ME)
36 | end
37 | end
38 |
39 | % For Simulink.Signal objects
40 | [isGlobal, obj, ~] = isGlobalDataStore(block);
41 | if isGlobal
42 | sampleTimeDs = obj.SampleTime;
43 | if (isInherited(sampleTime) || isempty(sampleTime)) && ~isempty(sampleTimeDs)
44 | sampleTime = sampleTimeDs;
45 | end
46 | end
47 |
48 | % 2) Get the CompiledSampleTime
49 | compiledSampleTime = get_param(block, 'CompiledSampleTime');
50 | if iscell(compiledSampleTime)
51 | compiledSampleTime = cell2mat(compiledSampleTime);
52 | end
53 |
54 | % Get the first row only. Documentation doesn't say what the second row is for,
55 | % and it contains zeros
56 | compiledSampleTime = compiledSampleTime(:,1);
57 |
58 | % Finally: Determine which to return. If the compiled time is available, always
59 | % return it because it could be different from the sample time.
60 | if ~isInherited(compiledSampleTime)
61 | time = compiledSampleTime;
62 | elseif isempty(sampleTime)
63 | time = compiledSampleTime;
64 | else
65 | time = sampleTime;
66 | end
67 | end
68 |
69 | function b = isInherited(time)
70 | if ~iscell(time)
71 | b = time == -1;
72 | else
73 | b = false;
74 | end
75 | end
--------------------------------------------------------------------------------
/src/Interface/getDataType_MJ.m:
--------------------------------------------------------------------------------
1 | function types = getDataType_MJ(blocks)
2 | % GETDATATYPE_MJ Return the block data type, for each Inport and Outport.
3 | %
4 | % Inputs:
5 | % blocks Array of block paths or handles.
6 | %
7 | % Outputs:
8 | % types Cell array of structs.
9 | %
10 | % Example:
11 | % >> getDataType_MJ('model/In1')
12 | % ans =
13 | % struct with fields:
14 | % Inport: []
15 | % Outport: 'Inherit: auto'
16 |
17 | blocks = inputToNumeric(blocks);
18 |
19 | % Get block types
20 | blockTypes = get_param(blocks, 'BlockType');
21 | if ~iscell(blockTypes) || length(blockTypes) == 1
22 | blockTypes = {blockTypes};
23 | end
24 |
25 | % Create empty struct cell array
26 | types = struct('Inport', [], 'Outport', []);
27 | types = repmat({types}, size(blocks));
28 |
29 | for i = 1:length(blocks)
30 | b = blocks(i);
31 |
32 | if any(find(strcmp(blockTypes{i}, {'Inport', 'FromFile'})))
33 | types{i}.Outport = get_param(b, 'OutDataTypeStr');
34 |
35 | elseif strcmp(blockTypes{i}, 'FromSpreadsheet')
36 | t = get_param(b, 'OutDataTypeStr');
37 | portHandles = get_param(b, 'PortHandles');
38 | nOut = length(portHandles.Outport);
39 | types{i}.Outport = repmat(t, nOut, 1);
40 |
41 | elseif strcmp(blockTypes{i}, 'Outport')
42 | types{i}.Inport = get_param(b, 'OutDataTypeStr');
43 |
44 | elseif strcmp(blockTypes{i}, 'ToFile')
45 | types{i}.Inport = get_param(b, 'SaveFormat');
46 |
47 | elseif strcmp(blockTypes{i}, 'ToWorkspace')
48 | workspaceData = evalin('base', 'whos');
49 | idx = ismember({workspaceData.name}, get_param(b, 'VariableName'));
50 | if any(idx)
51 | match = workspaceData(idx);
52 | types{i}.Inport = match.class;
53 | end
54 |
55 | elseif strcmp(blockTypes{i}, 'FromWorkspace')
56 | workspaceData = evalin('base', 'whos');
57 | idx = ismember({workspaceData.name}, get_param(b, 'VariableName'));
58 | if any(idx)
59 | match = workspaceData(idx);
60 | types{i}.Outport = match.class;
61 | else
62 | types{i}.Outport = get_param(b, 'OutDataTypeStr');
63 | end
64 |
65 | elseif strcmp(blockTypes{i}, {'DataStoreRead'})
66 | [isGlobal, obj, ~] = isGlobalDataStore(b);
67 | if isGlobal
68 | types{i}.Outport = obj.DataType;
69 | else
70 | error(['Block ''' getfullname(b) ''' is not a global data store and should not be on the interface.']);
71 | end
72 |
73 | elseif strcmp(blockTypes{i}, {'DataStoreWrite'})
74 | [isGlobal, obj, ~] = isGlobalDataStore(b);
75 | if isGlobal
76 | types{i}.Inport = obj.DataType;
77 | else
78 | error(['Block ''' getfullname(b) ''' is not a global data store and should not be on the interface.']);
79 | end
80 |
81 | elseif isSimulinkFcn(b)
82 | [intype, outtype] = getFcnArgsType(b);
83 | types{i}.Inport = char(intype);
84 | types{i}.Outport = char(outtype);
85 |
86 | elseif isLibraryLink(b)
87 | %types{i} = 'N/A';
88 |
89 | elseif strcmp(blockTypes{i}, 'ModelReference')
90 | %types{i} = 'N/A';
91 | end
92 | end
93 |
94 | % Just return the struct if it's for one element only
95 | if length(types) == 1
96 | types = types{1};
97 | end
98 | end
--------------------------------------------------------------------------------
/doc/tex/macros.tex:
--------------------------------------------------------------------------------
1 | \usepackage{xspace}
2 |
3 | \newcommand{\args}[1] {\textit{#1}}
4 | \newcommand{\cmd}[1] {\texttt{#1}} % Use for command window commands, e.g., \cmd{svn up}
5 | \newcommand{\block}[1] {\textsf{#1}} % Use for Simulink block names, e.g., \cmd{Subsystem1}
6 | \newcommand{\signal}[1] {\textsf{#1}} % Use for Simulink block names, e.g., \cmd{Subsystem1}
7 | \newcommand{\ring}[1] {\textsf{#1}} % Use for files names and paths
8 | \newcommand{\keyword}[1] {\texttt{#1}} % Use for keywords of programming languages, e.g., \keyword{while}
9 | \newcommand{\file}[1] {\texttt{#1}} % Use for files names and paths
10 | \newcommand{\param}[1] {\textsf{#1}} % Use for block parameter names, e.g., \param{BlockType}
11 |
12 | % Matlab Products
13 | \newcommand{\matlab}{\textsc{Matlab}\@\xspace}
14 | \newcommand{\Matlab}{\textsc{Matlab}\@\xspace}
15 | \newcommand{\Simulink}{Simulink\@\xspace}
16 | \newcommand{\simulink}{Simulink\@\xspace}
17 | \newcommand{\SDV}{Simulink Design Verifier\@\xspace}
18 | \newcommand{\mpath}{\Matlab search path\@\xspace}
19 |
20 | % Block Names (not BlockType)
21 | \newcommand{\ds}{\block{Data Store}\@\xspace}
22 | \newcommand{\DSM}{\block{Data Store Memory}\@\xspace}
23 | \newcommand{\DSR}{\block{Data Store Read}\@\xspace}
24 | \newcommand{\DSW}{\block{Data Store Write}\@\xspace}
25 | \newcommand{\DSRW}{\block{Data Store Read/Write}\@\xspace}
26 | \newcommand{\DSMRW}{\block{Data Store Memory/Read/Write}\@\xspace}
27 |
28 | \newcommand{\goto}{\block{Goto}\@\xspace}
29 | \newcommand{\from}{\block{From}\@\xspace}
30 |
31 | \newcommand{\inport}{\block{Inport}\@\xspace}
32 | \newcommand{\outport}{\block{Outport}\@\xspace}
33 |
34 | \newcommand{\argin}{\block{ArgIn}\@\xspace}
35 | \newcommand{\argout}{\block{ArgOut}\@\xspace}
36 |
37 | \newcommand{\constant}{\block{Constant}\@\xspace}
38 | \newcommand{\ground}{\block{Ground}\@\xspace}
39 | \newcommand{\subsystem}{\block{Subsystem}\@\xspace}
40 |
41 | \newcommand{\logic}{\block{Logical Operator}\@\xspace}
42 | \newcommand{\relational}{\block{Relational Operator}\@\xspace}
43 | \newcommand{\ifblk}{\block{If}\@\xspace}
44 | \newcommand{\switch}{\block{Switch}\@\xspace}
45 | \newcommand{\merge}{\block{Merge}\@\xspace}
46 |
47 | \newcommand{\docblock}{\block{DocBlock}\@\xspace}
48 |
49 | \newcommand{\trigger}{\block{Trigger}\@\xspace}
50 |
51 | \newcommand{\simfunc}{\block{Simulink Function}\@\xspace}
52 | \newcommand{\simfunccaller}{\block{Function Caller}\@\xspace}
53 |
54 | \newcommand{\toworkspace}{\block{To Workspace}\@\xspace}
55 | \newcommand{\fromworkspace}{\block{From Workspace}\@\xspace}
56 |
57 | \newcommand{\tofile}{\block{To File}\@\xspace}
58 | \newcommand{\fromfile}{\block{From File}\@\xspace}
59 |
60 | \newcommand{\fromspreadsheet}{\block{From Spreadsheet}\@\xspace}
61 |
62 | \newcommand{\modelref}{\block{Model Reference}\@\xspace}
63 | \newcommand{\library}{\block{Library}\@\xspace}
64 | \newcommand{\librarylink}{\block{Library Link}\@\xspace}
65 |
66 | % Commonly used parameters
67 | \newcommand{\AND}{\param{AND}\@\xspace}
68 | \newcommand{\OR}{\param{OR}\@\xspace}
69 | \newcommand{\NOT}{\param{NOT}\@\xspace}
70 | \newcommand{\NOR}{\param{NOR}\@\xspace}
71 | \newcommand{\NAND}{\param{NAND}\@\xspace}
72 | \newcommand{\XOR}{\param{XOR}\@\xspace}
73 | \newcommand{\NXOR}{\param{NXOR}\@\xspace}
74 |
75 | % Common Abbreviations
76 | % Example
77 | \newcommand{\eg}{\textrm{e.g.,}\@\xspace}
78 |
79 | % That Is To Say
80 | \newcommand{\ie}{\textrm{i.e.,}\@\xspace}
81 |
82 | % And So On
83 | \newcommand{\etc}{\textrm{etc.}\@\xspace}
84 |
85 | % And Others
86 | \newcommand{\etal}{\textrm{et al.}\@\xspace}
87 |
88 | % With Respect To
89 | \newcommand{\wrt}{\textrm{w.r.t.}\@\xspace}
90 |
91 | % Vice Versa
92 | \newcommand{\vrsa}{\textrm{vice versa}\@\xspace}
93 |
94 | % Symbols
95 |
96 | \usepackage{amssymb}
97 | \newcommand{\checkbox}{\makebox[0pt][l]{$\square$}\raisebox{.15ex}{\hspace{0.1em}$\checkmark$}}%
98 | \newcommand{\uncheckbox}{$\square$~}%
99 |
--------------------------------------------------------------------------------
/src/Interface/getDimensions.m:
--------------------------------------------------------------------------------
1 | function dims = getDimensions(blocks)
2 | % GETDIMENSIONS Return the block dimensions, for each Inport and Outport.
3 | %
4 | % Inputs:
5 | % blocks Array of block paths or handles.
6 | %
7 | % Outputs:
8 | % dims Cell array of structs.
9 | %
10 | % Example:
11 | % >> getDimensions{'model/In1')
12 | % ans =
13 | % struct with fields:
14 | % Inport: 1
15 | % Outport: []
16 |
17 | blocks = inputToNumeric(blocks);
18 |
19 | % Get block types
20 | blockTypes = get_param(blocks, 'BlockType');
21 | if ~iscell(blockTypes) || length(blockTypes) == 1
22 | blockTypes = {blockTypes};
23 | end
24 |
25 | % Create empty struct cell array
26 | dims = struct('Inport', [], 'Outport', []);
27 | dims = repmat({dims}, size(blocks));
28 |
29 | for i = 1:length(blocks)
30 | b = blocks(i);
31 |
32 | if strcmp(blockTypes{i}, 'Inport')
33 | dims{i}.Outport = get_param(b, 'PortDimensions');
34 |
35 | elseif strcmp(blockTypes{i}, 'Outport')
36 | dims{i}.Inport = get_param(b, 'PortDimensions');
37 |
38 | elseif isSimulinkFcn(b) && ~isLibraryLink(b)
39 | [indim, outdim] = getFcnArgsDim(b);
40 | dims{i}.Inport = cell2mat(indim);
41 | dims{i}.Outport = cell2mat(outdim);
42 |
43 | elseif strcmp(blockTypes{i}, 'DataStoreRead')
44 | [isGlobal, obj, ~] = isGlobalDataStore(b);
45 | if isGlobal
46 | dims{i}.Outport = obj.Dimensions;
47 | else
48 | error(['Block ''' getfullname(b) ''' is not a global data store and should not be on the interface.']);
49 | end
50 |
51 | elseif strcmp(blockTypes{i}, 'DataStoreWrite')
52 | [isGlobal, obj, ~] = isGlobalDataStore(b);
53 | if isGlobal
54 | dims{i}.Inport = obj.Dimensions;
55 | else
56 | error(['Block ''' getfullname(b) ''' is not a global data store and should not be on the interface.']);
57 | end
58 |
59 | elseif any(find(strcmp(blockTypes{i}, {'ToFile', 'FromFile'})))
60 | %
61 |
62 | elseif strcmp(blockTypes{i}, 'FromSpreadsheet')
63 | % Only one dimensional signals are supported
64 | dims{i}.Outport = ones(1, length(get_param(b, 'PortConnectivity')));
65 |
66 | elseif strcmp(blockTypes{i}, 'ToWorkspace')
67 | workspaceData = evalin('base', 'whos');
68 | idx = ismember({workspaceData.name}, get_param(b, 'VariableName'));
69 | if any(idx)
70 | match = workspaceData(idx);
71 | dims{i}.Inport = match.size;
72 | end
73 |
74 | elseif strcmp(blockTypes{i}, 'FromWorkspace')
75 | workspaceData = evalin('base', 'whos');
76 | idx = ismember({workspaceData.name}, get_param(b, 'VariableName'));
77 | if any(idx)
78 | match = workspaceData(idx);
79 | dims{i}.Outport = match.size;
80 | end
81 |
82 | elseif strcmp(blockTypes{i}, 'ModelReference')
83 | %
84 | end
85 |
86 |
87 | try
88 | dims{i}.Inport = str2num(dims{i}.Inport);
89 | catch
90 | end
91 | try
92 | dims{i}.Outport = str2num(dims{i}.Outport);
93 | catch
94 | end
95 | end
96 |
97 | % Just return the struct if it's for one element only
98 | if length(dims) == 1
99 | dims = dims{1};
100 | end
101 | end
--------------------------------------------------------------------------------
/src/Guidelines/guidelineSelector.m:
--------------------------------------------------------------------------------
1 | function varargout = guidelineSelector(varargin)
2 | % GUIDELINESELECTOR MATLAB code for guidelineSelector.fig
3 | % GUIDELINESELECTOR, by itself, creates a new GUIDELINESELECTOR or raises the existing
4 | % singleton*.
5 | %
6 | % H = GUIDELINESELECTOR returns the handle to a new GUIDELINESELECTOR or the handle to
7 | % the existing singleton*.
8 | %
9 | % GUIDELINESELECTOR('CALLBACK',hObject,eventData,handles,...) calls the local
10 | % function named CALLBACK in GUIDELINESELECTOR.M with the given input arguments.
11 | %
12 | % GUIDELINESELECTOR('Property','Value',...) creates a new GUIDELINESELECTOR or raises the
13 | % existing singleton*. Starting from the left, property value pairs are
14 | % applied to the GUI before guidelineSelector_OpeningFcn gets called. An
15 | % unrecognized property name or invalid value makes property application
16 | % stop. All inputs are passed to guidelineSelector_OpeningFcn via varargin.
17 | %
18 | % *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one
19 | % instance to run (singleton)".
20 | %
21 | % See also: GUIDE, GUIDATA, GUIHANDLES
22 |
23 | % Edit the above text to modify the response to help guidelineSelector
24 |
25 | % Last Modified by GUIDE v2.5 02-Oct-2018 16:40:16
26 |
27 | % Begin initialization code - DO NOT EDIT
28 | gui_Singleton = 1;
29 | gui_State = struct('gui_Name', mfilename, ...
30 | 'gui_Singleton', gui_Singleton, ...
31 | 'gui_OpeningFcn', @guidelineSelector_OpeningFcn, ...
32 | 'gui_OutputFcn', @guidelineSelector_OutputFcn, ...
33 | 'gui_LayoutFcn', [] , ...
34 | 'gui_Callback', []);
35 | if nargin && ischar(varargin{1})
36 | gui_State.gui_Callback = str2func(varargin{1});
37 | end
38 |
39 | if nargout
40 | [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
41 | else
42 | gui_mainfcn(gui_State, varargin{:});
43 | end
44 | % End initialization code - DO NOT EDIT
45 |
46 |
47 | % --- Executes just before guidelineSelector is made visible.
48 | function guidelineSelector_OpeningFcn(hObject, eventdata, handles, varargin)
49 | % This function has no output args, see OutputFcn.
50 | % hObject handle to figure
51 | % eventdata reserved - to be defined in a future version of MATLAB
52 | % handles structure with handles and user data (see GUIDATA)
53 | % varargin command line arguments to guidelineSelector (see VARARGIN)
54 |
55 | % Choose default command line output for guidelineSelector
56 | handles.output = '';
57 |
58 | % Update handles structure
59 | guidata(hObject, handles);
60 |
61 | % UIWAIT makes guidelineSelector wait for user response (see UIRESUME)
62 | uiwait(handles.figure1);
63 |
64 |
65 | % --- Outputs from this function are returned to the command line.
66 | function varargout = guidelineSelector_OutputFcn(hObject, eventdata, handles)
67 | % varargout cell array for returning output args (see VARARGOUT);
68 | % hObject handle to figure
69 | % eventdata reserved - to be defined in a future version of MATLAB
70 | % handles structure with handles and user data (see GUIDATA)
71 |
72 | % Set the output values, depending on which button was pressed
73 | if strcmp(handles.output, 'OK')
74 | g0001 = get(handles.checkbox0001, 'Value');
75 | g0002 = get(handles.checkbox0002, 'Value');
76 | g0003 = get(handles.checkbox0003, 'Value');
77 | g0004 = get(handles.checkbox0004, 'Value');
78 |
79 | varargout{1} = [g0001, g0002, g0003, g0004];
80 | else
81 | varargout{1} = [0 0 0 0];
82 | end
83 |
84 | % The figure can be deleted now
85 | delete(handles.figure1);
86 |
87 |
88 | % --- Executes on button press in buttonOK.
89 | function buttonOK_Callback(hObject, eventdata, handles)
90 | % hObject handle to buttonOK (see GCBO)
91 | % eventdata reserved - to be defined in a future version of MATLAB
92 | % handles structure with handles and user data (see GUIDATA)
93 |
94 | % Update which button was pressed
95 | handles.output = get(hObject, 'String');
96 |
97 | % Update handles structure
98 | guidata(hObject, handles);
99 |
100 | % Use UIRESUME instead of delete because the OutputFcn needs
101 | % to get the updated handles structure.
102 | uiresume(handles.figure1);
103 |
104 |
105 | % --- Executes on button press in checkbox0001.
106 | function checkbox0001_Callback(hObject, eventdata, handles)
107 | % hObject handle to checkbox0001 (see GCBO)
108 | % eventdata reserved - to be defined in a future version of MATLAB
109 | % handles structure with handles and user data (see GUIDATA)
110 |
111 | % Hint: get(hObject,'Value') returns toggle state of checkbox0001
112 |
113 |
114 | % --- Executes on button press in checkbox0002.
115 | function checkbox0002_Callback(hObject, eventdata, handles)
116 | % hObject handle to checkbox0002 (see GCBO)
117 | % eventdata reserved - to be defined in a future version of MATLAB
118 | % handles structure with handles and user data (see GUIDATA)
119 |
120 | % Hint: get(hObject,'Value') returns toggle state of checkbox0002
121 |
122 |
123 | % --- Executes on button press in checkbox0003.
124 | function checkbox0003_Callback(hObject, eventdata, handles)
125 | % hObject handle to checkbox0003 (see GCBO)
126 | % eventdata reserved - to be defined in a future version of MATLAB
127 | % handles structure with handles and user data (see GUIDATA)
128 |
129 | % Hint: get(hObject,'Value') returns toggle state of checkbox0003
130 |
131 |
132 | % --- Executes on button press in checkbox0004.
133 | function checkbox0004_Callback(hObject, eventdata, handles)
134 | % hObject handle to checkbox0004 (see GCBO)
135 | % eventdata reserved - to be defined in a future version of MATLAB
136 | % handles structure with handles and user data (see GUIDATA)
137 |
138 | % Hint: get(hObject,'Value') returns toggle state of checkbox0004
139 |
140 |
141 | % --- Executes when user attempts to close figure1.
142 | function figure1_CloseRequestFcn(hObject, eventdata, handles)
143 | % hObject handle to figure1 (see GCBO)
144 | % eventdata reserved - to be defined in a future version of MATLAB
145 | % handles structure with handles and user data (see GUIDATA)
146 |
147 | if isequal(get(hObject, 'waitstatus'), 'waiting')
148 | % The GUI is still in UIWAIT, use UIRESUME
149 | uiresume(hObject);
150 | else
151 | % The GUI is no longer waiting, just close it
152 | delete(hObject);
153 | end
154 |
--------------------------------------------------------------------------------
/src/isGlobalDataStore.m:
--------------------------------------------------------------------------------
1 | function [isGlobal, obj, location] = isGlobalDataStore(block)
2 | % ISGLOBALDATASTORE Determine if a Data Store Read/Write block is a global data
3 | % store, that is, it has a corresponding Simulink.Signal in the base workspace
4 | % or linked data dictionary.
5 | %
6 | % Inputs:
7 | % block Block path or handle.
8 | %
9 | % Outputs:
10 | % isGlobal Whether the block is a global data store (1) or not (0).
11 | % obj Simulink.Signal object corresponding to the block.
12 | % location Object where the Simulink.Signal definition resides.
13 | %
14 | % Example:
15 | % >> [gbl, obj, loc] = isGlobalStateStore('Example/Data Store Write1')
16 | %
17 | % glb =
18 | % logical
19 | % 1
20 | %
21 | % obj =
22 | % Signal with properties:
23 | % CoderInfo: [1x1 Simulink.CoderInfo]
24 | % Description: ''
25 | % DataType: 'double'
26 | % Min: []
27 | % Max: []
28 | % Unit: ''
29 | % Dimensions: [1 3]
30 | % DimensionsMode: 'Fixed'
31 | % Complexity: 'real'
32 | % SampleTime: -1
33 | % InitialValue: ''
34 | %
35 | % loc =
36 | % Dictionary with properties:
37 | % DataSources: {0x1 cell}
38 | % HasAccessToBaseWorkspace: 0
39 | % EnableAccessToBaseWorkspace: 0
40 | % HasUnsavedChanges: 1
41 | % NumberOfEntries: 3
42 |
43 | % TODO: Figure out if when the 'EnableAccessToBaseWorkspace' parameter is
44 | % true, this affects the results of this function. See:
45 | % https://www.mathworks.com/help/simulink/slref/simulink.data.dictionary-class.html#d120e428542
46 |
47 | % Convert input to path
48 | block = [get_param(block, 'Parent') '/' get_param(block, 'Name')];
49 |
50 | % Default vaules:
51 | % If we can't find the associated Memory block, that means that it is a Simuilink.Signal
52 | % elsewhere, but can't detetmine where. This can happen if a model has a
53 | % global data store, but the Simuilink.Signal is not loaded in any workspace.
54 | isGlobal = true;
55 | obj = [];
56 | location = 'unknown';
57 |
58 | blockType = get_param(block, 'BlockType');
59 | if ~any(find(strcmp(blockType, {'DataStoreRead', 'DataStoreWrite'})))
60 | isGlobal = false;
61 | obj = [];
62 | location = [];
63 | else
64 | name = get_param(block, 'DataStoreName');
65 |
66 | % 0) Model
67 | % Check if the model contains an associated Data Store Memory block. If
68 | % it does, it takes precedence over all other definitions. This is NOT a
69 | % global data store.
70 |
71 | % Search for any associated memory block at the same level or above
72 | % Even if there is a workspace Simulink.Signal with the same name, the
73 | % Data Store Read/Write block will use the Memory block in the model.
74 | parent = get_param(block, 'Parent');
75 | root = bdroot(block);
76 | memoryAll = find_system(root, 'BlockType', 'DataStoreMemory', 'DataStoreName', name);
77 | memoryHere = find_system(parent, 'SearchDepth', 1, 'BlockType', 'DataStoreMemory', 'DataStoreName', name);
78 | memoryHereAndBelow = find_system(parent, 'BlockType', 'DataStoreMemory', 'DataStoreName', name);
79 | memoryBelow = setdiff(memoryHereAndBelow, memoryHere);
80 | memoryInScope = setdiff(memoryAll, memoryBelow);
81 | if ~isempty(memoryInScope)
82 | isGlobal = false;
83 | obj = [];
84 | location = []; % TODO: Find lowest common ancestor (Get from Rescope Tool)
85 | else
86 |
87 | % 1) Model Workspace
88 | % Check model workspace next, because it takes precedence over
89 | % data dictionary or base workspace definitions. This is NOT a
90 | % global data store.
91 | workspace = get_param(bdroot, 'modelworkspace');
92 | try
93 | ds = getVariable(workspace, name);
94 | catch ME
95 | if strcmp(ME.identifier, 'Simulink:Data:WksUndefinedVariable')
96 | ds = [];
97 | else
98 | rethrow(ME)
99 | end
100 | end
101 |
102 | if ~isempty(ds)
103 | isGlobal = false;
104 | obj = ds;
105 | location = workspace;
106 | return
107 | end
108 |
109 | % 2) Data Dictionary
110 | % Check data dictionary next, because if a model is linked to a dictionary,
111 | % it no longer refers to the base workspace.
112 | dataDictName = get_param(root, 'DataDictionary');
113 | if ~isempty(dataDictName)
114 | dataDict = Simulink.data.dictionary.open(dataDictName);
115 | dataSection = getSection(dataDict, 'Design Data');
116 | try
117 | dataEntry = getEntry(dataSection, name);
118 | catch ME
119 | if strcmp(ME.identifier, 'SLDD:sldd:EntryNotFound')
120 | dataEntry = [];
121 | else
122 | rethrow(ME)
123 | end
124 | end
125 | if ~isempty(dataEntry)
126 | isGlobal = true;
127 | obj = getValue(dataEntry);
128 | location = dataDict;
129 | return
130 | else
131 | isGlobal = false;
132 | obj = [];
133 | location = [];
134 | return
135 | end
136 |
137 | % 3) Base Workspace
138 | else
139 | workspaceData = evalin('base', 'whos');
140 | idx = ismember({workspaceData.class}, 'Simulink.Signal');
141 | allDs = workspaceData(idx);
142 | match = strcmp({allDs.name}, name);
143 | if any(match)
144 | ds = allDs(match);
145 | isGlobal = true;
146 | obj = evalin('base', ds.name);
147 | location = 'base';
148 | end
149 | end
150 | end
151 | end
152 | end
--------------------------------------------------------------------------------
/src/subToSimFcn.m:
--------------------------------------------------------------------------------
1 | function subToSimFcn(subsystem, simulinkFcnName, visibility)
2 | % SUBTOSIMFUNC Convert a Subsystem into a Simulink Function.
3 | %
4 | % Inputs:
5 | % subsystem Path of a subsystem to be converted.
6 | % simulinkFcnName Name of the Simulink Function to be created.
7 | % visibility Set function visibility to 'scoped' or 'global'.
8 | %
9 | % Outputs:
10 | % N/A
11 | %
12 | % Example:
13 | % subToSimFunc('Demo_Example/f_Sensor_Trip_1', 'f_Sensor_Trip_i', 'scoped')
14 |
15 | %% Input Validation
16 | % Check that the subsystem model is loaded
17 | try
18 | assert(ischar(subsystem));
19 | assert(bdIsLoaded(bdroot(subsystem)));
20 | catch
21 | error('Invalid subsystem. Model may not be loaded or name is invalid.');
22 | end
23 |
24 | % Check that the function name is valid
25 | try
26 | assert(isvarname(simulinkFcnName));
27 | catch
28 | error('Invalid function name. Use a valid MATLAB variable name.');
29 | end
30 |
31 | % Check that the function visibility is valid
32 | try
33 | assert(strcmp(visibility, 'scoped') || strcmp(visibility, 'global'));
34 | catch
35 | error('Invalid function visibility. Use scoped/global visibility.');
36 | end
37 |
38 | %% Add Trigger to Subsystem
39 | % Break library link
40 | set_param(subsystem, 'LinkStatus', 'none');
41 |
42 | % Adding the trigger block to the subsystem
43 | triggerPath = [subsystem, '/', simulinkFcnName];
44 | add_block('simulink/Ports & Subsystems/Trigger', triggerPath);
45 |
46 | % Set trigger block parameters
47 | set_param(triggerPath, 'TriggerType', 'function-call');
48 | try
49 | set_param(triggerPath, 'IsSimulinkFunction', 'on', 'FunctionName', simulinkFcnName);
50 | catch ME
51 | if strcmp(ME.identifier, 'Simulink:Commands:ParamUnknown')
52 | % Version of Simulink is pre-R2014b so doesn't support Simulink Functions
53 | v = ver('Simulink');
54 | warning(ME.identifier, ['Simulink ' v.Release ' does not support Simulink Functions.']);
55 | else
56 | rethrow(ME)
57 | end
58 | end
59 | try
60 | set_param(triggerPath, 'FunctionVisibility', visibility);
61 | catch ME
62 | if strcmp(ME.identifier, 'Simulink:Commands:ParamUnknown')
63 | % Version of Simulink is pre-R2017b so doesn't support scoping
64 | v = ver('Simulink');
65 | warning(ME.identifier, ['Simulink ' v.Release ' does not support Simulink Function scope.']);
66 | else
67 | rethrow(ME)
68 | end
69 | end
70 |
71 | %% Set subsystem parameters
72 | set_param(subsystem, 'TreatAsAtomicUnit', 'on');
73 |
74 | %% Convert Inports to ArgIns
75 | % Create array of all the inports in the subsystem
76 | allInports = find_system(subsystem, 'SearchDepth', 1, 'BlockType', 'Inport');
77 |
78 | % Get the parameters for all inports in the subsystem
79 | inportParameters = getPortParameters(allInports);
80 |
81 | % Replace inports with argument inputs
82 | replace_block(subsystem, 'SearchDepth', 1, 'BlockType', 'Inport', 'ArgIn', 'noprompt');
83 |
84 | % Create array of all the argIns in the Simulink Function
85 | allArgIns = find_system(subsystem, 'SearchDepth', 1, 'BlockType', 'ArgIn');
86 |
87 | % Set the parameters for all the argument inputs
88 | setArgumentParameters(allArgIns, inportParameters);
89 |
90 | %% Convert Outports to ArgOuts
91 | % Create array of all the outports in the subsystem
92 | allOutports = find_system(subsystem, 'SearchDepth', 1, 'BlockType', 'Outport');
93 |
94 | % Get the parameters for all outports in the subsystem
95 | outportParameters = getPortParameters(allOutports);
96 |
97 | % Replace outports with argument outputs
98 | replace_block(subsystem, 'SearchDepth', 1, 'BlockType', 'Outport', 'ArgOut', 'noprompt');
99 |
100 | % Create array of all the argOuts for the Simulink Function
101 | allArgOuts = find_system(subsystem, 'SearchDepth', 1, 'BlockType', 'ArgOut');
102 |
103 | % Set the parameters for all the argument outputs
104 | setArgumentParameters(allArgOuts, outportParameters);
105 | end
106 |
107 | function parameters = getPortParameters(ports)
108 | % getPortParameters Get the parameters for an inport or outport.
109 | %
110 | % Inputs:
111 | % ports Cell array of inports or outports.
112 | %
113 | % Outputs:
114 | % parameters Cell array of parameters including:
115 | % 1) Port
116 | % 2) OutMin
117 | % 3) OutMax
118 | % 4) OutDataTypeStr
119 | % 5) LockScale
120 | % 6) PortDimensions
121 | % 7) ArgumentName
122 | %
123 | % Example:
124 | % parameters = getPortParameters({'System/Subsystem/Inport1'})
125 | %
126 | % ans =
127 | % 1x7 cell array
128 | % {'1'} {'[]'} {'[]'} {'boolean'} {'off'} {'on'} {'Inport1'}
129 |
130 | %% Get the port parameters
131 | % Init array of parameters for the ports
132 | parameters = cell(length(ports), 7);
133 | % Loop through each port
134 | for port = 1:length(ports)
135 | % Get the port name by splitting the pathname by the backslash
136 | splitPortPath = split(ports{port}, '/');
137 | % The port name is the last index of splitPortPath
138 | portName = splitPortPath{end};
139 | % Get the port number
140 | parameters{port, 1} = get_param(ports{port}, 'Port');
141 | % Get the port minimum output
142 | parameters{port, 2} = get_param(ports{port}, 'OutMin');
143 | % Get the port maximum output
144 | parameters{port, 3} = get_param(ports{port}, 'OutMax');
145 | % Get the port data type
146 | parameters{port, 4} = get_param(ports{port}, 'OutDataTypeStr');
147 | % If data type is set to inherit, set to double by default
148 | try
149 | assert(not(strcmp(parameters{port, 4}, 'Inherit: auto')));
150 | catch
151 | disp([portName, ...
152 | ' data type was set to ''Inherit: auto''', ...
153 | ' - setting to ''double''...']);
154 | parameters{port, 4} = 'double';
155 | end
156 | % Get the port lock scale
157 | parameters{port, 5} = get_param(ports{port}, 'LockScale');
158 | % Get the port dimension
159 | parameters{port, 6} = get_param(ports{port}, 'PortDimensions');
160 | % If port dimension is set to inherit, set to 1 by default
161 | try
162 | assert(not(strcmp(parameters{port, 6}, '-1')))
163 | catch
164 | disp([portName, ...
165 | ' dimension was set to ''-1''', ...
166 | ' - setting to ''1''...']);
167 | parameters{port, 6} = '1';
168 | end
169 | % Remove spaces from port name to create a valid variable name
170 | parameters{port, 7} = genvarname(portName);
171 | end
172 | end
173 |
174 | function setArgumentParameters(arguments, parameters)
175 | % setArgumentParameters Set argIn or ArgOut parameters.
176 | %
177 | % Inputs:
178 | % arguments Cell array of argIns or argOuts.
179 | % parameters Cell array of parameters for each argument.
180 | %
181 | % Outputs:
182 | % N/A
183 | %
184 | % Example:
185 | % setArgumentParameters({'System/Subsystem/argIn1'}, ...
186 | % {'1', '[]', '[]', 'boolean', 'off', 'on', 'Inport1'})
187 |
188 | %% Set the argument parameters
189 | % Loop through each argument
190 | for arg = 1:length(arguments)
191 | % Set the parameters for each argument
192 | set_param(arguments{arg}, 'Port', parameters{arg, 1}, ...
193 | 'OutMin', parameters{arg, 2}, ...
194 | 'OutMax', parameters{arg, 3}, ...
195 | 'OutDataTypeStr', parameters{arg, 4}, ...
196 | 'LockScale', parameters{arg, 5}, ...
197 | 'PortDimensions', parameters{arg, 6}, ...
198 | 'ArgumentName', parameters{arg, 7});
199 | end
200 | end
--------------------------------------------------------------------------------
/src/sl_customization.m:
--------------------------------------------------------------------------------
1 | %% Register custom menu function to beginning of Simulink Editor's context menu
2 | function sl_customization(cm)
3 | cm.addCustomMenuFcn('Simulink:PreContextMenu', @getSLModuleTool);
4 | end
5 |
6 | %% Define custom menu function: Changing Scope
7 | function schemaFcns = getSLModuleTool(callbackInfo)
8 | schemaFcns = {};
9 | selection = find_system(gcs, 'Type', 'block', 'Selected', 'on');
10 | selectedFcns = isSimulinkFcn(selection);
11 |
12 | % Check if the Simulink version supports Simulink Functions
13 | v = ver('Simulink');
14 | if str2double(v.Version) > 8.3 % Greater than 2014a
15 | verOK = true;
16 | else
17 | verOK = false;
18 | end
19 |
20 | if isempty(gcbs)
21 | schemaFcns{end+1} = @FcnCreatorSchema;
22 | schemaFcns{end+1} = @GuidelineSchema;
23 | schemaFcns{end+1} = @InterfaceSchema;
24 | elseif verOK && isSubsystem(gcbs) && ~isSimulinkFcn(gcbs) && ~isempty(gcbs)
25 | schemaFcns{end+1} = @ConvToSimFcnSchema;
26 | elseif any(selectedFcns) && ~isempty(gcbs)
27 | schemaFcns{end+1} = @ChangeFcnScopeSchema;
28 | schemaFcns{end+1} = @FcnCreatorLocalSchema;
29 | end
30 | end
31 |
32 | %% Define action: Convert Subsystem to Simulink Function
33 | function schema = ConvToSimFcnSchema(callbackInfo)
34 | schema = sl_container_schema;
35 | schema.label = 'Convert Subsystem';
36 | schema.ChildrenFcns = {@toScopedSimFcn, @toGlobalSimFcn};
37 | end
38 |
39 | function schema = toScopedSimFcn(callbackInfo)
40 | schema = sl_action_schema;
41 | schema.label = 'To Scoped Simulink Function';
42 | schema.userdata = 'toScopedSimFcn';
43 | schema.callback = @toScopedSimFcnCallback;
44 | end
45 |
46 | function toScopedSimFcnCallback(callbackInfo)
47 | simulinkFcnName = reqSimFcnName();
48 | subsystem = gcbs;
49 | subToSimFcn(subsystem{1}, simulinkFcnName, 'scoped');
50 | end
51 |
52 | function schema = toGlobalSimFcn(callbackInfo)
53 | schema = sl_action_schema;
54 | schema.label = 'To Global Simulink Function';
55 | schema.userdata = 'toGlobalSimFcn';
56 | schema.callback = @toGlobalSimFcnCallback;
57 | end
58 |
59 | function toGlobalSimFcnCallback(callbackInfo)
60 | simulinkFcnName = reqSimFcnName();
61 | subsystem = gcbs;
62 | subToSimFcn(subsystem{1}, simulinkFcnName, 'global');
63 | end
64 |
65 | %% Define action: Create Function Caller for Local Function
66 | function schema = FcnCreatorLocalSchema(callbackInfo)
67 | schema = sl_action_schema;
68 | schema.label = 'Create Function Caller';
69 | schema.userdata = 'createFcnCallerLocal';
70 | schema.callback = @createFcnCallerLocalCallback;
71 | end
72 |
73 | function createFcnCallerLocalCallback(callbackInfo)
74 | createFcnCallerLocal(gcbs);
75 | end
76 |
77 | %% Define action: Create Function Caller for Any Function
78 | function schema = FcnCreatorSchema(callbackInfo)
79 | schema = sl_action_schema;
80 | schema.label = 'Call Function...';
81 | schema.userdata = 'createFcnCaller';
82 | schema.callback = @FcnCreatorCallback;
83 | end
84 |
85 | function FcnCreatorCallback(callbackInfo)
86 | sys = gcs; % Save in case it changes
87 |
88 | % Position the caller in the center of the model
89 | bounds = bounds_of_sim_objects(find_system(sys, 'SearchDepth', 1));
90 | x = ((bounds(3)-bounds(1))/2) + bounds(1);
91 | y = ((bounds(4)-bounds(2))/2) + bounds(2);
92 |
93 | [fcns, proto] = getCallableFunctions(sys);
94 | idx = functionGUI(fcns, proto); % let user make selection
95 | f = char(fcns(idx));
96 | p = char(proto(idx));
97 |
98 | if ~isempty(f)
99 | % Load model is necessary
100 | i = regexp(f, '/', 'once');
101 | mdl = f(1:i-1);
102 | loaded = bdIsLoaded(mdl);
103 | if ~loaded
104 | load_system(mdl);
105 | end
106 |
107 | createFcnCaller(sys, f, 'prototype', p, 'position', [x, y]);
108 |
109 | % Close model if necessary
110 | if ~loaded
111 | close_system(mdl, 0);
112 | end
113 | end
114 | end
115 |
116 | %% Define action: Change Scope
117 | function schema = ChangeFcnScopeSchema(callbackInfo)
118 | schema = sl_container_schema;
119 | schema.label = 'Change Function Scope';
120 | schema.userdata = 'changeFcnScope';
121 |
122 | % Get the functions that are selected and determine their scope
123 | selection = find_system(gcs, 'Type', 'block', 'Selected', 'on');
124 | selectedFcns = isSimulinkFcn(selection);
125 | fcns = {};
126 | for i = 1:length(selectedFcns)
127 | if selectedFcns(i)
128 | fcns{end+1,1} = selection{i};
129 | end
130 | end
131 | scopes = getFcnScope(fcns);
132 |
133 | % Show conversion operations depending on scope
134 | anyGlobal = any(contains2(scopes, char(Scope.Global)));
135 | anyScoped = any(contains2(scopes, char(Scope.Scoped)));
136 | anyLocal = any(contains2(scopes, char(Scope.Local)));
137 | if anyScoped || anyLocal
138 | schema.childrenFcns{end+1} = @GlobalFcnSchema;
139 | end
140 | if anyGlobal || anyLocal
141 | schema.childrenFcns{end+1} = @ScopedFcnSchema;
142 | end
143 | if anyGlobal || anyScoped || anyLocal
144 | schema.childrenFcns{end+1} = @LocalFcnSchema;
145 | end
146 |
147 | % If there are functions selected, but the functions don't have a scope
148 | if isempty(schema.childrenFcns)
149 | schema.state = 'Disabled';
150 | end
151 |
152 | garbageCollection();
153 | end
154 |
155 | %% Define action: Convert to Global
156 | function schema = GlobalFcnSchema(callbackInfo)
157 | schema = sl_action_schema;
158 | schema.label = 'To Global Function';
159 | schema.userdata = 'convertToGlobalFcn';
160 | schema.callback = @convertToGlobalFcnCallback;
161 | end
162 |
163 | function convertToGlobalFcnCallback(callbackInfo)
164 | setFcnScope(gcbs, Scope.Global, '');
165 | end
166 |
167 | %% Define action: Convert to Scoped
168 | function schema = ScopedFcnSchema(callbackInfo)
169 | schema = sl_action_schema;
170 | schema.label = 'To Scoped Exported Function';
171 | schema.userdata = 'convertToScopedFcn';
172 | schema.callback = @convertToScopedFcnCallback;
173 | end
174 |
175 | function convertToScopedFcnCallback(callbackInfo)
176 | setFcnScope(gcbs, Scope.Scoped, '');
177 | end
178 |
179 | %% Define action: Convert to Local
180 | function schema = LocalFcnSchema(callbackInfo)
181 | schema = sl_container_schema;
182 | schema.label = 'To Scoped Local Function';
183 | schema.userdata = 'convertToLocalFcn';
184 | schema.childrenFcns = {@LocalFcnNewSchema, @LocalFcnExistSchema};
185 | end
186 |
187 | function schema = LocalFcnNewSchema(callbackInfo)
188 | schema = sl_action_schema;
189 | schema.label = 'In New Subsystem';
190 | schema.userdata = 'convertToLocalFcnNew';
191 | schema.callback = @convertToLocalFcnNewCallback;
192 | end
193 |
194 | function convertToLocalFcnNewCallback(callbackInfo)
195 | setFcnScope(gcbs, Scope.Local, '');
196 | end
197 |
198 | function schema = LocalFcnExistSchema(callbackInfo)
199 | schema = sl_action_schema;
200 | schema.label = 'In Existing Subsystem';
201 | schema.userdata = 'convertToLocalFcnExist';
202 | schema.callback = @convertToLocalFcnExistCallback;
203 | end
204 |
205 | function convertToLocalFcnExistCallback(callbackInfo)
206 | subsystem = subsystemGUI(bdroot);
207 | if ~isempty(subsystem)
208 | setFcnScope(gcbs, Scope.Local, subsystem);
209 | end
210 | end
211 |
212 | %% Define action: Check Guidelines
213 | function schema = GuidelineSchema(callbackInfo)
214 | schema = sl_action_schema;
215 | schema.label = 'Check Guidelines...';
216 | schema.userdata = 'checkGuidelines';
217 | schema.callback = @CheckGuidelines;
218 | end
219 |
220 | function CheckGuidelines(callbackInfo)
221 | sys = gcs;
222 | guidelines = guidelineSelector;
223 | if guidelines(1)
224 | [blocks, locations] = guideline0001(sys);
225 | fprintf('Guideline 1 ''Simulink Function Placement'' violations: ');
226 | if isempty(blocks)
227 | fprintf('None\n');
228 | else
229 | fprintf('\n');
230 | for i = 1:length(blocks)
231 | fprintf('\t%s can be moved to %s\n', replaceNewline(blocks{i}), replaceNewline(locations{i}));
232 | end
233 | fprintf('\n');
234 | end
235 | end
236 | if guidelines(2)
237 | blocks = guideline0002(sys);
238 | fprintf('Guideline 2 ''Simulink Function Visibility'' violations: ');
239 | if isempty(blocks)
240 | fprintf('None\n');
241 | else
242 | fprintf('\n');
243 | for i = 1:length(blocks)
244 | fprintf('\t%s\n', replaceNewline(blocks{i}));
245 | end
246 | fprintf('\n');
247 | end
248 | end
249 | if guidelines(3)
250 | [blocks, shadows] = guideline0003(sys);
251 | fprintf('Guideline 3 ''Simulink Function Shadowing'' violations: ');
252 | if isempty(blocks)
253 | fprintf('None\n');
254 | else
255 | fprintf('\n');
256 | for i = 1:length(blocks)
257 | if ~isempty(shadows{i})
258 | fprintf('\t%s is shadowed by:\n\t\t%s\n', replaceNewline(blocks{i}), strjoin(replaceNewline(shadows{i}), '\n\t\t'));
259 | end
260 | fprintf('\n');
261 | end
262 | end
263 | end
264 | if guidelines(4)
265 | blocks = guideline0004(sys);
266 | fprintf('Guideline 4 ''Use of Base Workspace'' violations: ');
267 | if isempty(blocks)
268 | fprintf('None\n');
269 | else
270 | fprintf('\n');
271 | for i = 1:length(blocks)
272 | fprintf('\t%s\n', replaceNewline(blocks{i}));
273 | end
274 | fprintf('\n');
275 | end
276 | end
277 |
278 | garbageCollection();
279 | end
280 |
281 | %% Define menu: Model Interface
282 | function schema = InterfaceSchema(callbackInfo)
283 | schema = sl_container_schema;
284 | schema.label = 'Interface';
285 | schema.ChildrenFcns = {@ModelInterfaceSchema, @PrintInterfaceSchema, @DeleteInterface, @PrintDependencies};
286 | end
287 |
288 | function schema = ModelInterfaceSchema(callbackInfo)
289 | schema = sl_action_schema;
290 | schema.label = 'Show Interface';
291 | schema.callback = @showInterfaceCallback;
292 | end
293 |
294 | function showInterfaceCallback(callbackInfo)
295 |
296 | garbageCollection();
297 |
298 | sys = bdroot(gcs);
299 | objName = [sys '_InterfaceObject'];
300 | eval(['global ' objName ';']);
301 |
302 | if interface_exists(sys)
303 | eval([objName ' = load_interface(sys);']);
304 | answer = questdlg('An interface already exists. Do you wish to replace it?', 'Interface Exists');
305 | if strcmp(answer, 'Yes')
306 | % Delete old representation
307 | eval([objName '.delete();'])
308 |
309 | % Create new interface
310 | eval([objName ' = Interface(sys);']);
311 | eval([objName ' = ' objName '.model();']);
312 | end
313 | else
314 | eval([objName ' = Interface(sys);']);
315 | eval([objName ' = ' objName '.model;']);
316 | end
317 | eval([objName '.saveInterfaceMat;']);
318 | end
319 |
320 | %% Define menu: Print Interface
321 | function schema = PrintInterfaceSchema(callbackInfo)
322 | schema = sl_action_schema;
323 | schema.label = 'Print Interface';
324 | schema.callback = @printInterfaceCallback;
325 | end
326 |
327 | function printInterfaceCallback(callbackInfo)
328 | sys = bdroot(gcs);
329 | objName = [sys '_InterfaceObject'];
330 | if interface_exists(sys)
331 | eval([objName ' = load_interface(sys);']);
332 | else
333 | eval([objName ' = Interface(sys);']);
334 | end
335 | eval([objName '.print();']);
336 |
337 | garbageCollection();
338 | end
339 |
340 | %% Delete Interface
341 | function schema = DeleteInterface(callbackInfo)
342 | schema = sl_action_schema;
343 | schema.label = 'Delete Interface';
344 | schema.userdata = 'DeleteInterface';
345 | schema.callback = @deleteInterfaceCallback;
346 |
347 | % Hide the delete option when there is nothing to delete
348 | sys = bdroot(gcs);
349 | if interface_exists(sys)
350 | schema.state = 'Enabled';
351 | else
352 | schema.state = 'Disabled';
353 | end
354 | end
355 |
356 | function deleteInterfaceCallback(callbackInfo)
357 | sys = bdroot(gcs);
358 | objName = [sys '_InterfaceObject'];
359 | eval(['global ' objName ';']);
360 |
361 | eval([objName ' = load_interface(sys);']);
362 |
363 | eval([objName ' = delete(' objName ');']);
364 | eval(['clear global ' objName ';']);
365 |
366 | garbageCollection();
367 | end
368 |
369 | function filename = get_interface_filename(sys)
370 | syspath = get_param(sys, 'FileName');
371 | [path, name, ~] = fileparts(syspath);
372 | ext = '.mat';
373 | filename = fullfile(path, [name '_Interface' ext]);
374 | end
375 |
376 | function e = interface_exists(sys)
377 | % INTERFACE_EXISTS Determine if there exists an interface for a model.
378 | objName = [sys '_InterfaceObject'];
379 | eval(['global ' objName ';']);
380 | eval(['objEmpty = isempty(' objName ');']);
381 |
382 | filename = get_interface_filename(sys);
383 |
384 | if objEmpty
385 | if isfile(filename)
386 | e = true;
387 | else
388 | e = false;
389 | end
390 | else
391 | e = true;
392 | end
393 | end
394 |
395 | function obj = load_interface(sys)
396 | filename = get_interface_filename(sys);
397 | if interface_exists(sys)
398 | obj = load(filename);
399 | obj = obj.obj;
400 | end
401 | end
402 |
403 | %% Print dependencies
404 | function schema = PrintDependencies(callbackInfo)
405 | schema = sl_action_schema;
406 | schema.label = 'Print Dependencies';
407 | schema.userdata = 'PrintDependencies';
408 | schema.callback = @printDependenciesCallback;
409 | end
410 |
411 | function printDependenciesCallback(callbackInfo)
412 | sys = bdroot(gcs);
413 | dependencies(sys);
414 | garbageCollection();
415 | end
416 |
417 | %% Garbage collection for objects
418 | function garbageCollection()
419 | globals = who('global');
420 |
421 | suffix = 'InterfaceObject';
422 | suffixLen = length(suffix) + 1;
423 |
424 | sysAll = cellfun(@(x) x(1:end-suffixLen), globals, 'un', 0);
425 | allSysOpen = find_system('SearchDepth', 0);
426 | globalHasSysOpen = ismember(sysAll, allSysOpen);
427 |
428 | for i = 1:length(globals)
429 | isInterfaceName = ~isempty(strfind(globals{i}, suffix));
430 | if isInterfaceName
431 | eval(['global ' globals{i} ';']) % Get this object
432 | if ~globalHasSysOpen(i) % Has no associated model open
433 | eval(['x =~ isempty(' globals{i} ');']);
434 | if x
435 | eval(['clearvars -global ' globals{i} ';']);
436 | %eval([globals{i} '.delete;']);
437 | end
438 | else % There is a system open that matches the object name
439 | % A different instance of the same model could be open, so we
440 | % check that the model handles match
441 | sameHdl = false;
442 | try
443 | eval(['objHdl = ' globals{i} '.getHandle;']);
444 | sysHdl = get_param(sysAll{i}, 'Handle');
445 | sameHdl = (objHdl == sysHdl);
446 | catch
447 | continue
448 | end
449 |
450 | if ~sameHdl %|| ~ishandle(objHdl
451 | eval(['clearvars -global ' globals{i} ';']);
452 | %else
453 | %eval([globals{i} '.delete;']);
454 | end
455 | end
456 | end
457 | end
458 | end
459 |
--------------------------------------------------------------------------------
/src/Interface/InterfaceItem.m:
--------------------------------------------------------------------------------
1 | classdef InterfaceItem
2 | properties
3 | BlockType % BlockType.
4 | InterfaceType % Input, Output, or Export.
5 | Handle % Handle of the item that is on the interface.
6 | Name % Name.
7 | Fullpath % Fullpath.
8 | DataType % Output or input types.
9 | Dimensions % Struct of Inport and Outport dimensions.
10 | SampleTime % SameTime.
11 |
12 | % Visual Representation
13 | InterfaceHandle % If the block is represented on the interface by another
14 | % block, this is the handle to that block (not
15 | % applicable for Inports and Outports).
16 | InterfacePath % Fullpath.
17 | GroundHandle % Handle(s) of Ground blocks (or Goto for ports).
18 | GroundPath % Fullpath.
19 | TerminatorHandle % Handle(s) of Terminators blocks (or From for ports).
20 | TerminatorPath % Fullpath.
21 | end
22 | methods (Access = public)
23 | function obj = InterfaceItem(handle)
24 | if nargin == 1
25 | % Perform checks before creating an InterfaceItem
26 | [valid, ~] = itemTypeCheck(handle);
27 | if ~valid
28 | error(['Block ''' get_param(obj.Handle, 'Name') ''' is not a valid InterfaceItem.']);
29 | end
30 |
31 | obj.Handle = inputToNumeric(handle);
32 | obj = autoGetData(obj);
33 | elseif nargin > 1
34 | error('Too many inputs provided.');
35 | else
36 | error('Not enough inputs provided.');
37 | end
38 | end
39 | function b = eq(obj1, obj2)
40 | % EQ Check if two InterfaceItems are equal.
41 | %
42 | % Inputs:
43 | % obj1 InterfaceItem.
44 | % obj2 InterfaceItem.
45 | %
46 | % Outputs:
47 | % b Whether or not inputs are equal (1), or not (0).
48 |
49 | if obj1.Handle == obj2.Handle
50 | b = true;
51 | else
52 | b = false;
53 | end
54 | end
55 | function print(obj)
56 | % PRINT Print the item to the Command Window.
57 | %
58 | % Inputs:
59 | % obj InterfaceItem.
60 | %
61 | % Outputs:
62 | % N/A
63 |
64 | % TODO: Currently assumes one sample time. There can be
65 | % multiple times
66 |
67 | if isSimulinkFcn(obj.Handle)
68 | argsIn = find_system(obj.Handle, 'SearchDepth', 1, 'BlockType', 'ArgIn');
69 | argsOut = find_system(obj.Handle, 'SearchDepth', 1, 'BlockType', 'ArgOut');
70 | nIn = length(argsIn);
71 | nOut = length(argsOut);
72 | else
73 | handles = get_param(obj.Handle, 'PortHandles');
74 | nIn = length(handles.Inport);
75 | nOut = length(handles.Outport);
76 | end
77 |
78 | oneInport = (nIn == 1);
79 | oneOutport = (nOut == 1);
80 |
81 | dt = obj.DataType;
82 | dim = obj.Dimensions;
83 | time = obj.SampleTime;
84 |
85 | if strcmp(obj.BlockType, 'ModelReference') || isLibraryLink(obj.Handle)
86 | if isempty(time)
87 | time_i = 'N/A';
88 | elseif size(time,1) > 1 || size(time,2) > 1 % Non-scalar
89 | time_i = char(strjoin(string(time), ', '));
90 | time_i = ['[' time_i ']'];
91 | else
92 | time_i = time;
93 | end
94 |
95 | if isnumeric(time_i) && rem(abs(time_i), 1) == 0
96 | time_format = '%i';
97 | elseif ischar(time_i)
98 | time_format = '%s';
99 | else
100 | time_format = '%.4f';
101 | end
102 | fprintf(['%s, N/A, N/A, ' time_format '\n'], obj.Fullpath, time_i);
103 | return
104 | end
105 |
106 | % Only 1 port
107 | if xor(oneInport, oneOutport)
108 |
109 | if oneInport
110 | dt = dt.Inport;
111 | dim = dim.Inport;
112 | else
113 | dt = dt.Outport;
114 | dim = dim.Outport;
115 | end
116 |
117 | % Account for data that is empty or an array
118 | if isempty(dt)
119 | dt = 'N/A';
120 | end
121 |
122 | if isempty(dim)
123 | dim = 'N/A';
124 | elseif size(dim,1) > 1 || size(dim,2) > 1 % Non-scalar
125 | dim = ['[' regexprep(num2str(dim), ' +', ', ') ']'];
126 | end
127 |
128 | if isempty(time)
129 | time_i = 'N/A';
130 | elseif size(time,1) > 1 || size(time,2) > 1 % Non-scalar
131 | time_i = char(strjoin(string(time), ', '));
132 | time_i = ['[' time_i ']'];
133 | else
134 | time_i = time;
135 | end
136 |
137 | % Account for different formatting
138 | dim_format = '%i';
139 | if ischar(dim)
140 | dim_format = '%s';
141 | end
142 |
143 | if isnumeric(time_i) && rem(abs(time_i), 1) == 0
144 | time_format = '%i';
145 | elseif ischar(time_i)
146 | time_format = '%s';
147 | else
148 | time_format = '%.4f';
149 | end
150 |
151 | % Print
152 | fprintf(['%s, %s, ' dim_format ', ' time_format '\n'], obj.Fullpath, dt, dim, time_i);
153 |
154 | % Multiple ports
155 | else
156 | fprintf('%s \n', obj.Fullpath);
157 |
158 | if nIn > 0
159 | fprintf('\t\tIn: ');
160 | for i = 1:nIn
161 | % Account for data that is empty or in an array
162 | if isempty(dt.Inport)
163 | dt_i = 'N/A';
164 | else
165 | dt_i = dt.Inport(i,:);
166 | end
167 |
168 | if isempty(dim.Inport)
169 | dim_i = 'N/A';
170 | else
171 | dim_i = dim.Inport(i);
172 | end
173 |
174 | if isempty(time)
175 | time_i = 'N/A';
176 | elseif size(time,1) > 1 || size(time,2) > 1 % Non-scalar
177 | time_i = char(strjoin(string(time), ', '));
178 | time_i = ['[' time_i ']'];
179 | else
180 | time_i = time;
181 | end
182 |
183 | % Separate from previous port
184 | if i ~= 1
185 | fprintf('; ');
186 | end
187 | if nIn > 4 && i > 1
188 | fprintf('\n\t\t ');
189 | end
190 |
191 | % Account for different formatting
192 | if ischar(dim_i)
193 | dim_format = '%s';
194 | else
195 | dim_format = '%i';
196 | end
197 |
198 | time_format = '%.4f';
199 | if isnumeric(time_i) && rem(abs(time_i), 1) == 0
200 | time_format = '%i';
201 | elseif ischar(time_i)
202 | time_format = '%s';
203 | else
204 | time_format = '%.4f';
205 | end
206 |
207 | % Print
208 | fprintf(['%s, ' dim_format ', ' time_format], dt_i, dim_i, time_i);
209 | end
210 | end
211 |
212 | if nOut > 0
213 | if nIn > 0
214 | fprintf('\n');
215 | end
216 | fprintf('\t\tOut: ');
217 | for i = 1:nOut
218 | % Account for data that is empty or in an array
219 | if isempty(dt.Outport)
220 | dt_i = 'N/A';
221 | else
222 | dt_i = dt.Outport(i,:);
223 | end
224 |
225 | if isempty(dim.Outport)
226 | dim_i = 'N/A';
227 | else
228 | dim_i = dim.Outport(i);
229 | end
230 |
231 | if isempty(time)
232 | time_i = 'N/A';
233 | elseif size(time,1) > 1 || size(time,2) > 1 % Non-scalar
234 | time_i = char(strjoin(string(time), ', '));
235 | time_i = ['[' time_i ']'];
236 | else
237 | time_i = time;
238 | end
239 |
240 | % Separate from previous port
241 | if i ~= 1
242 | fprintf('; ');
243 | end
244 | if nIn > 4 && i > 1
245 | fprintf('\n\t\t ');
246 | end
247 |
248 | % Account for different formatting
249 | if ischar(dim_i)
250 | dim_format = '%s';
251 | else
252 | dim_format = '%i';
253 | end
254 |
255 | if isnumeric(time_i) && rem(abs(time_i), 1) == 0
256 | time_format = '%i';
257 | elseif ischar(time_i)
258 | time_format = '%s';
259 | else
260 | time_format = '%.4f';
261 | end
262 |
263 | % Print
264 | fprintf(['%s, ' dim_format ', ' time_format], dt_i, dim_i, time_i);
265 | end
266 | fprintf('\n');
267 | end
268 | end
269 | end
270 | function obj = deleteFromModel(obj)
271 | % DELETEFROMMODEL Delete the representation of the item in the
272 | % model.
273 | obj = obj.updateHandle;
274 | if any2(strcmp(obj.BlockType, {'Inport', 'Outport'}))
275 | obj = deleteGrndTrm(obj);
276 | % Move inport/outport back
277 | try
278 | moveToConnectedPort(obj.InterfaceHandle, 30);
279 | redraw_block_lines(obj.InterfaceHandle, 'AutoRouting', 'smart');
280 | catch ME
281 | if ~strcmp(ME.identifier, 'Simulink:Commands:InvSimulinkObjHandle') % The model was closed
282 | rethrow(ME)
283 | end
284 | end
285 | else
286 | try
287 | delete(obj.InterfaceHandle);
288 | obj = deleteGrndTrm(obj);
289 | catch ME
290 | if ~strcmp(ME.identifier, 'MATLAB:hg:udd_interface:CannotDelete') % Already deleted
291 | rethrow(ME)
292 | end
293 | end
294 | end
295 | obj.InterfaceHandle = [];
296 | obj.InterfacePath = [];
297 | end
298 | function obj = updateHandle(obj)
299 | % UPDATEHANDLE Re-populate the handle properties.
300 | % Try getting the handles according to the fullpath. If the
301 | % interface has changed (e.g., inport was deleted), the handle will
302 | % not be found.
303 | try
304 | obj.Handle = get_param(obj.Fullpath, 'Handle');
305 | catch
306 | obj.Handle = [];
307 | end
308 |
309 | try
310 | obj.InterfaceHandle = get_param(obj.InterfacePath, 'Handle');
311 | catch
312 | obj.InterfaceHandle = [];
313 | end
314 |
315 | try
316 | for i = 1:length(obj.GroundHandle)
317 | if iscell(obj.GroundPath)
318 | g = obj.GroundPath{i};
319 | else
320 | g = obj.GroundPath;
321 | end
322 | g = get_param(g, 'Handle');
323 | obj.GroundHandle(i) = g;
324 | end
325 | catch
326 | obj.GroundHandle = [];
327 | end
328 |
329 | try
330 | for j = 1:length(obj.TerminatorHandle)
331 | if iscell(obj.TerminatorPath)
332 | t = obj.TerminatorPath{j};
333 | else
334 | t = obj.TerminatorPath;
335 | end
336 | t = get_param(t, 'Handle');
337 | obj.TerminatorHandle(j) = t;
338 | end
339 | catch
340 | obj.TerminatorHandle = [];
341 | end
342 | end
343 | end
344 | methods (Access = private)
345 | function obj = autoGetData(obj)
346 | % AUTOGETDATA Automatically populate the item's fields based on the model.
347 | %
348 | % Inputs:
349 | % obj InterfaceItem.
350 | %
351 | % Outputs:
352 | %
353 | % obj InterfaceItem.
354 |
355 | % BLOCKTYPE
356 | obj.BlockType = get_param(obj.Handle, 'BlockType');
357 |
358 | % INTERFACETYPE
359 | [~, obj.InterfaceType] = itemTypeCheck(obj.Handle);
360 |
361 | % NAME
362 | obj.Name = replaceNewline(get_param(obj.Handle, 'Name'));
363 |
364 | % FULLPATH
365 | obj.Fullpath = replaceNewline(getfullname(obj.Handle));
366 |
367 | % DATATYPE
368 | obj.DataType = getDataType_MJ(obj.Handle);
369 |
370 | % DIMENSIONS
371 | obj.Dimensions = getDimensions(obj.Handle);
372 |
373 | % SAMPLE TIME
374 | obj.SampleTime = getSampleTime(obj.Handle);
375 |
376 | % INTERFACEHANDLE, INERFACEPATH, ETC.
377 | % Added when the interface is modelled only.
378 | end
379 | function obj = deleteGrndTrm(obj)
380 | % DELETEGRNDTRM Delete the ground and terminator elements with their
381 | % lines.
382 | for i = 1:length(obj.GroundHandle)
383 | g = obj.GroundHandle(i);
384 | if ishandle(g)
385 | if strcmp(obj.BlockType, 'Outport')
386 | goto2Line(bdroot(obj.Fullpath), obj.GroundHandle);
387 | else
388 | lines = get_param(g, 'LineHandles');
389 | delete(lines.Outport);
390 | delete(g);
391 | end
392 | end
393 | end
394 | obj.GroundHandle = [];
395 | obj.GroundPath = [];
396 |
397 | for j = 1:length(obj.TerminatorHandle)
398 | t = obj.TerminatorHandle(j);
399 | if ishandle(t)
400 | if strcmp(obj.BlockType, 'Inport')
401 | goto2Line(bdroot(obj.Fullpath), obj.TerminatorHandle);
402 | else
403 | lines = get_param(t, 'LineHandles');
404 | delete(lines.Inport);
405 | delete(t);
406 | end
407 | end
408 | end
409 | obj.TerminatorHandle = [];
410 | obj.TerminatorPath = [];
411 |
412 | end
413 | end
414 | end
415 | function [valid, type] = itemTypeCheck(handle)
416 | % ITEMTYPECHECK Check if the item is one of the supported BlockTypes. Return the
417 | % InterfaceType.
418 | %
419 | % Inputs:
420 | % handle Handle to a block.
421 | %
422 | % Outputs:
423 | % valid Whether or not it is a supported InterfaceItem block.
424 | % type 'Input', 'Output', 'Export'
425 |
426 | blocktype = get_param(handle, 'BlockType');
427 | in = {'Inport', 'FromFile', 'FromWorkspace', 'FromSpreadsheet', 'DataStoreRead'};
428 | out = {'Outport', 'ToFile', 'ToWorkspace', 'DataStoreWrite'};
429 |
430 | if isempty(blocktype)
431 | type = '';
432 | valid = false;
433 | return
434 | end
435 |
436 | if any2(find(strcmp(in, blocktype)))
437 | type = 'Input';
438 | valid = true;
439 | elseif any2(find(strcmp(out, blocktype)))
440 | type = 'Output';
441 | valid = true;
442 | elseif isSimulinkFcn(handle)
443 | type = 'Export';
444 | valid = true;
445 | else
446 | type = '';
447 | valid = false;
448 | end
449 | end
--------------------------------------------------------------------------------
/doc/tex/SimulinkModule_UserGuide.tex:
--------------------------------------------------------------------------------
1 | \documentclass{article}
2 |
3 | %%%%%%%%%%%%%%%%%%%%%%%%%
4 | % Packages & Macros
5 | %%%%%%%%%%%%%%%%%%%%%%%%%
6 |
7 | % For including graphics
8 | \usepackage{graphicx}
9 |
10 | % For title page
11 | \usepackage{datetime}
12 | \newdateformat{monthyeardate}{\monthname[\THEMONTH] \THEYEAR}
13 |
14 | % For supporting linking
15 | \usepackage{hyperref}
16 | \hypersetup{colorlinks,urlcolor=blue,linkcolor=blue}
17 |
18 | % For supporting subfigure captions
19 | \usepackage{subcaption}
20 |
21 | % For making text listings (Figure 7 and 8)
22 | \usepackage{listings}
23 |
24 | % For string comparison in macros
25 | \usepackage{etoolbox}
26 |
27 | % For table colouring (in command line tables)
28 | %\usepackage{colortbl}
29 |
30 | %%%%%%%%%%%%%%%%%%%%%%%%%
31 | % Tool-Specific Macros
32 | %%%%%%%%%%%%%%%%%%%%%%%%%
33 | \input{macros}
34 |
35 | \newcommand{\ToolName}{Simulink Module Tool\@\xspace}
36 |
37 | \newcommand{\menu}[1]{%
38 | \ifstrequal{#1}{1}{Call Function}{}%
39 | \ifstrequal{#1}{2}{Create Function Caller}{}%
40 | \ifstrequal{#1}{3}{Change Function Scope}{}%
41 | \ifstrequal{#1}{4}{Check Guidelines}{}%
42 | \ifstrequal{#1}{5}{Show Interface}{}%
43 | \ifstrequal{#1}{6}{Print Interface}{}%
44 | \ifstrequal{#1}{7}{Print Dependencies}{}%
45 | \ifstrequal{#1}{8}{Delete Interface}{}%
46 | \ifstrequal{#1}{9}{Convert Subsystem}{}%
47 | }
48 |
49 | \newcommand{\func}[1]{%
50 | \ifthenelse{\equal{#1}{1}}{CreateFcnCallerLocal}{}%
51 | \ifthenelse{\equal{#1}{2}}{CreateFcnCaller}{}%
52 | \ifthenelse{\equal{#1}{3}}{setFcnScope}{}%
53 | \ifthenelse{\equal{#1}{4}}{?}{}%
54 | \ifthenelse{\equal{#1}{5}}{?}{}%
55 | \ifthenelse{\equal{#1}{6}}{?}{}%
56 | }
57 |
58 | \newcommand{\demoName}{\cmd{Demo}\@\xspace}
59 |
60 | %%%%%%%%%%%%%%%%%%%%%%%%%
61 | % Document
62 | %%%%%%%%%%%%%%%%%%%%%%%%%
63 |
64 | \begin{document}
65 |
66 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
67 | % Title Page
68 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
69 | \title{\ToolName}
70 | \date{\monthyeardate\today}
71 | \maketitle
72 | \vfill
73 |
74 | \begin{figure}
75 | \centering
76 | \includegraphics{../figs/McSCert_Logo.pdf} \\
77 | McMaster Centre for Software Certification (McSCert)
78 | \end{figure}
79 |
80 | \newpage
81 |
82 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83 | % Table of Contents
84 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
85 | \tableofcontents
86 | \newpage
87 |
88 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
89 | % Introduction
90 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
91 | \section{Introduction}
92 |
93 | % Briefly, what is the tool?
94 | % Provide any background or references.
95 | The \ToolName performs several functions in order to support modular development for \Simulink models. A \Simulink module structure can be summarized by Figure~\ref{FIG:module}. This tool helps in scoping \simfunc{s}, displaying interfaces, and checking associated guidelines. The following sections explain each of the tool functions.
96 |
97 | \begin{figure}
98 | \centering
99 | \includegraphics[width=0.75\textwidth]{../figs/Module}
100 | \caption{\Simulink module structure based on C.}
101 | \label{FIG:module}
102 | \end{figure}
103 |
104 | \subsection{Simulink Functions}
105 | In \Simulink, a function can be defined via the \simfunc block, and invoked graphically via \simfunccaller blocks. In the modular programming approach to software development, a system is decomposed into modules. Each module must be able to hide information in its implementation, and only expose on the interface information what is to be shared with other modules. One can use \simfunc blocks to selectively hide or expose elements on the interface. However, a thorough understanding of the \simfunc block is necessary in order to know how the \emph{Function Visibility} parameter and location in the model impacts its accessibility and name qualification.
106 |
107 | The \ToolName assists developers with using \simfunc blocks in implementing \Simulink modules. The tool can automatically convert between the different scopes of \simfunc{s}, thereby changing whether it is exposed on the interface or local to the model. The tool also assists users in quickly calling \simfunc{s}, with their appropriate qualifiers, from any location in a model or parent hierarchy, as well as creating \simfunccaller blocks with their \emph{Function prototype}, \emph{Input argument specifications}, and \emph{Output argument specifications} parameters automatically populated (if possible).
108 |
109 | \subsection{Interfaces}
110 | A \Simulink model's interface is commonly considered to be comprised of the \inport{s} and \outport{s} of the top-level system. A module interface should make clear \emph{all} the communication of a module. The \fromfile, \fromspreadsheet, \fromworkspace blocks, and global \ds{s} that are read are also inputs to the model. Elements that are outputs of the model can also include \toworkspace, \tofile, and global \ds{s} that are written to. Additionally, \simfunc definitions can be exported from a model. %A complete definition of a \Simulink module interface is presented in~\cite{paper}.
111 |
112 | The \ToolName automatically extracts the interface of a \Simulink module and either represents it in the the root of the \Simulink module, or prints the interface to the Command Window.
113 |
114 | \subsection{Dependencies}
115 |
116 | A \Simulink model can have many dependencies in the form of \modelref{s}, \library linked blocks, and data dictionaries. These reside outside of the \Simulink module, but are necessary in order to be able to simulate and code generate the model.
117 |
118 | The \ToolName examines the model, determines which dependencies exist, and prints a list to the Command Window.
119 |
120 | \subsection{Guidelines}
121 | Guidelines relating to \simfunc{s} and interfaces are presented in~\cite{paper}. Tables \ref{tbl:guideline1}, \ref{tbl:guideline2}, \ref{tbl:guideline3}, and \ref{tbl:guideline4} outline the guidelines, and the tool automates the checking of these guidelines.
122 |
123 | % Is there more information?
124 | %\subsection*{More Information}
125 | %For more information on the tool and how it can be used in model-based development with \Simulink, please the paper:
126 |
127 | %\vspace{1em}
128 | %Monika Jaskolka, Vera Pantelic, Mark Lawford, and Alan Wassyng, ``Supporting Modularity for \Simulink Models", 2019, \textit{(Manuscript in Preparation)}.
129 |
130 | % Is there more information?
131 | %\subsection*{More Information}
132 | %For more about the theoretical background of ... and how they can be used, an interested reader is referred to:
133 | %
134 | %\vspace{1em}
135 | %
136 |
137 | \newpage
138 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
139 | % How to Use the Tool
140 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
141 | \section{How to Use the Tool}
142 | This section describes what must be done to setup the \ToolName, as well as how to use the tool.
143 |
144 | %---------------------------------------
145 | % What needs to be done before the tool can be used?
146 | % What needs to be done to a model in order for it to work on said model?
147 | %---------------------------------------
148 | \subsection{Prerequisites and Installation}
149 |
150 | \begin{enumerate}
151 | \item For full use of the tool, please use \matlab/\Simulink R2017b or newer.\footnote{Simulink functions were introduced in R2014b. The \emph{Function Visibility} parameter was introduced in R2017b.}
152 |
153 | \item To install the tool, use one of the following approaches:
154 | \begin{enumerate}
155 | \item \textbf{Download the \file{.zip} from GitHub}
156 | \begin{enumerate}
157 | \item Unzip the contents into your desired location.
158 | \item Add the unzipped folder and subfolders to your \mpath.
159 | \item Download the \href{https://github.com/McSCert/Simulink-Utility}{Simulink-Utility} in the same manner. Add the folder and subfolders to your \mpath also. This is a dependency for the tool to work correctly.
160 | \item Download the \href{https://github.com/McSCert/LineToGotoFrom}{LineToGotoFrom} tool in the same manner. Add the folder and subfolders to your \mpath also. This is a dependency for the tool to work correctly.
161 | \end{enumerate}
162 | \item \textbf{Use the Git command line}
163 | \begin{enumerate}
164 | \item Use the following command to download the tool and any necessary submodules.
165 | \begin{verbatim}
166 | git clone --recursive https://github.com/McSCert/Simulink-Module
167 | \end{verbatim}
168 | \item Add the folder and subfolders to your \mpath.
169 | \end{enumerate}
170 | \item \textbf{If you already have the files}
171 | \begin{enumerate}
172 | \item Add the tool folder and subfolders to your \mpath.
173 | \end{enumerate}
174 | \end{enumerate}
175 | \item Run \href{https://www.mathworks.com/help/simulink/ug/registering-customizations.html}{sl\_refresh\_customizations} to refresh the Context Menu.
176 | \item Ensure your model is open and unlocked.
177 | \end{enumerate}
178 |
179 | %---------------------------------------
180 | % How/when do you access the tool?
181 | %---------------------------------------
182 | \subsection{Getting Started}
183 | The tool can be used via the \Simulink Context Menu, which can be viewed by right-clicking in a model. The following options can be available, depending on what is selected in the model, and which version of \Matlab/\Simulink is used.
184 |
185 | \noindent
186 | Options available when no blocks are selected are (Figure~\ref{FIG:none_selected}):
187 | \begin{itemize}
188 | \item \emph{\menu{1}} %-- R2014b+
189 | \item \emph{\menu{4}}
190 | \item \emph{\menu{5}} %-- R2016a+
191 | \item \emph{\menu{6}} %-- R2016a+
192 | \item \emph{\menu{8}} %-- Only when an interface is shown in the module.
193 | \item \emph{\menu{7}}
194 | \end{itemize}
195 |
196 | \noindent
197 | Options available when one or more \simfunc blocks are selected (Figure~\ref{FIG:simfunc_selected}):
198 | \begin{itemize}
199 | \item \emph{\menu{3}} %-- R2017b+
200 | \item \emph{\menu{2}} %-- R2014b+
201 | \end{itemize}
202 |
203 | \noindent
204 | Options available when a \subsystem block is selected (Figure~\ref{FIG:subsystem_selected}):
205 | \begin{itemize}
206 | \item \emph{\menu{9}} %-- R2014b+
207 | \end{itemize}
208 |
209 | \begin{figure}[!htb]
210 | \centering
211 | \begin{subfigure}[b]{\textwidth}
212 | \centering
213 | \includegraphics[width=0.65\textwidth]{../figs/ContextMenu1}
214 | \caption{Menu options when no \simfunc{s} are selected.}
215 | \label{FIG:none_selected}
216 | \end{subfigure}
217 |
218 | \vspace{1em}%
219 |
220 | \begin{subfigure}[b]{\textwidth}
221 | \centering
222 | \includegraphics[width=\textwidth]{../figs/ContextMenu2}
223 | \caption{Menu options when one or more \simfunc{s} are selected.}
224 | \label{FIG:simfunc_selected}
225 | \end{subfigure}
226 |
227 | \vspace{1em}%
228 |
229 | \begin{subfigure}[b]{\textwidth}
230 | \centering
231 | \includegraphics[width=.85\textwidth]{../figs/ContextMenu3}
232 | \caption{Menu options when a \subsystem is selected.}
233 | \label{FIG:subsystem_selected}
234 | \end{subfigure}
235 |
236 | \caption{Simulink Context Menu with context-dependant tool options visible.}
237 | \label{FIG:contextMenu}
238 | \end{figure}
239 |
240 | %---------------------------------------
241 | % What are the main uses of the tool?
242 | %---------------------------------------
243 | \newpage
244 | \subsection{Functionality}
245 | This section describes the tool functionality when it is used from the \Simulink Context Menu (Figure~\ref{FIG:contextMenu}).
246 |
247 | %We will demonstrate on the model shown in Figure~\ref{FIG:examplemodel}.
248 |
249 | %\begin{figure}
250 | % \includegraphics[width=\columnwidth]{../figs/Demo}
251 | % \caption{A \Simulink model (in Interface Display view).}
252 | % \label{FIG:examplemodel}
253 | %\end{figure}
254 |
255 | %-------------------------
256 | \subsubsection{\menu{1}}
257 | %-------------------------
258 | \emph{Note: This option is not available in versions prior to R2014b.}
259 |
260 | Right-clicking anywhere in the model and then selecting \cmd{\menu{1}} from the Context Menu will display the user interface shown in Figure~\ref{FIG:gui}. The listbox shows all \simfunc{s} that can be called from that location in the model. Select a function, press OK, and a \simfunccaller will be created with its \keyword{Prototype}, \keyword{Input argument specifications}, and \keyword{Output argument specifications} parameters automatically populated.
261 |
262 | This function automates the following manual steps:
263 | \begin{enumerate}
264 | \item Drag and drop a \simfunc block from the User-Defined Functions library into the model.
265 | \item Open the \simfunc block parameters.
266 | \item Enter a \keyword{Prototype} from those available.
267 | \item Determine the input and output types and dimensions. Enter them into the \keyword{Input argument specifications} and \keyword{Output argument specifications} fields in the appropriate formatting.
268 | \end{enumerate}
269 | Moreover, it allows you to see which \simfunc{s} are available (\ie in scope) from any location in the model.
270 |
271 | \begin{figure}[htb]
272 | \centering
273 | \includegraphics[width=0.5\textwidth]{../figs/GUI}
274 | \caption{Select Function interface.}
275 | \label{FIG:gui}
276 | \end{figure}
277 |
278 | %-------------------------
279 | \subsubsection{\menu{3}}
280 | %-------------------------
281 | \emph{Note: This option is not available in versions prior to R2017b.}
282 |
283 | Right-clicking directly on one or more \simfunc blocks and then selecting \cmd{\menu{3}} from the Context Menu, will display options for changing the scope of the functions. An example is shown in Figure~\ref{FIG:demo2}.
284 |
285 | The scope of a Simulink function, \ie where it can be used, is determined by both its hierarchal \emph{placement} in the model in which it is defined, and its \emph{Function Visibility} parameter.
286 | The rules for determining the scope of a \simfunc are not straightforward. When a \simfunc is given global function visibility, it can be placed anywhere in a model, and will be available for use anywhere in the model hierarchy (\ie in any subsystems or in the parent model hierarchy). When a \simfunc is given scoped function visibility, its placement in the model affects its accessibility. If placed at root level, it is accessible in the model hierarchy. The difference between a global \simfunc and a scoped \simfunc placed at the root is in the way it is called. In the latter, the function name must be qualified with the model reference block name. If the scoped \simfunc is placed in a subsystem $S$ (\ie not at the root), it is no longer available outside of the model. Instead, it is available in the parent subsystem of $S$ and any descendants. %If a scoped \simfunc being placed in an atomic subsystem, it is accessible only inside the subsystem and its descendants.
287 |
288 | \begin{figure}
289 | \centering
290 | \includegraphics[width=\textwidth]{../figs/Demo2}
291 | \caption{Changing \simfunc scopes.}
292 | \label{FIG:demo2}
293 | \end{figure}
294 |
295 | %-------------------------
296 | \subsubsection{\menu{2}}
297 | %-------------------------
298 | \emph{Note: This option is not available in versions prior to R2014b.}
299 |
300 | Right-clicking on one or more \simfunc blocks and then selecting \cmd{\menu{2}} from the Context Menu, will automatically create corresponding \simfunccaller blocks for the selected functions. The \keyword{Prototype}, \keyword{Input argument specifications}, and \keyword{Output argument specifications} parameters of the new \simfunccaller are automatically populated. An example is shown in Figure~\ref{fig:demo1a}.
301 |
302 | \begin{figure}[!htb]
303 | \centering
304 | \begin{subfigure}[b]{\textwidth}
305 | \centering
306 | \includegraphics[width=\textwidth]{../figs/Demo1a}
307 | \caption{Select \menu{2} from the Context Menu.}
308 | \label{fig:demo1a}
309 | \end{subfigure}
310 |
311 | \vspace{1em}%
312 |
313 | \begin{subfigure}[b]{\textwidth}
314 | \centering
315 | \includegraphics[width=.75\textwidth]{../figs/Demo1b}
316 | \caption{New function callers are added.}
317 | \label{fig:demo1b}
318 | \end{subfigure}
319 | \caption{Example of Simulink Function Caller creation.}
320 | \label{fig:demo1}
321 | \end{figure}
322 |
323 | %-------------------------
324 | \subsubsection{\menu{9}}
325 | %-------------------------
326 | \emph{Note: This option is not available in versions prior to R2014a.}
327 |
328 | Right-clicking on a \subsystem and then selecting \cmd{\menu{9}}, and one of the two option from the Context Menu will convert a \subsystem block into a \simfunc. This will prompt the user for a function name, and perform several functions to reconfigure the \subsystem. This includes converting any \inport/\outport blocks to \argin/\argout blocks, adding a \trigger block, and setting various parameters.
329 |
330 | %-------------------------
331 | \subsubsection{\menu{4}}
332 | %-------------------------
333 | Right-clicking anywhere in the model and then selecting \cmd{\menu{4}} from the Context Menu will display the user interface shown in Figure~\ref{FIG:guideline}. The window shows all the guidelines that can be enabled by the user, and hovering over their names with the cursor will display a brief description of the guideline. The guidelines are detailed in Tables \ref{tbl:guideline1}, \ref{tbl:guideline2}, \ref{tbl:guideline3}, and \ref{tbl:guideline4}. Select one or more guidelines to check, press OK, and the Command Window will display any violations.
334 |
335 | \begin{figure}[htb]
336 | \centering
337 | \includegraphics[width=0.5\textwidth]{../figs/GuidelineSelector}
338 | \caption{Select guidelines GUI.}
339 | \label{FIG:guideline}
340 | \end{figure}
341 |
342 | \begin{table}
343 | \centering
344 | \caption{Guideline on \simfunc placement.}
345 | \label{tbl:guideline1}
346 | \begin{tabular}{|l|p{30em}|}
347 | \hline
348 | ID: Title & 1: \Simulink Function Placement \\ \hline
349 | Priority & Strongly Recommended \\ \hline
350 | \Matlab Version & R2014b and later \\ \hline
351 | Description & Position the \simfunc block in the lowest common parent of its corresponding \simfunccaller blocks. Do not position the \simfunc in the top layer for no reason. Avoid placing \simfunc blocks below their corresponding \simfunccaller blocks. \\ \hline
352 | Rationale & \checkbox Readability \newline
353 | \checkbox Verification and Validation \newline
354 | \checkbox Workflow \newline
355 | \checkbox Code Generation \newline
356 | \uncheckbox Simulation \\ \hline
357 | \end{tabular}
358 | \end{table}
359 |
360 | \begin{table}
361 | \centering
362 | \caption{Guideline on \simfunc visibility.}
363 | \label{tbl:guideline2}
364 | \begin{tabular}{|l|p{30em}|}
365 | \hline
366 | ID: Title & 2: \Simulink Function Visibility \\ \hline
367 | Priority & Strongly Recommended \\ \hline
368 | \Matlab Version & R2017b and later \\ \hline
369 | Description & Limit the \param{Function Visibility} parameter of the \simfunc block's trigger port to \param{scoped} if possible. \newline
370 | \includegraphics[scale=0.6]{../figs/FunctionVisibilityParam} \\ \hline
371 | Rationale & \checkbox Readability \newline
372 | \checkbox Verification and Validation \newline
373 | \checkbox Workflow \newline
374 | \checkbox Code Generation \newline
375 | \uncheckbox Simulation \\ \hline
376 | \end{tabular}
377 | \end{table}
378 |
379 | \begin{table}
380 | \centering
381 | \caption{Guideline on \simfunc shadowing.}
382 | \label{tbl:guideline3}
383 | \begin{tabular}{|l|p{30em}|}
384 | \hline
385 | ID: Title & 3: \Simulink Function Shadowing \\ \hline
386 | Priority & Strongly Recommended \\ \hline
387 | \Matlab Version & R2014b and later \\ \hline
388 | Description & Do not place \simfunc{s} with the same name and input/output arguments within each other's scope. \\ \hline
389 | Rationale & \checkbox Readability \newline
390 | \checkbox Verification and Validation \newline
391 | \checkbox Workflow \newline
392 | \uncheckbox Code Generation \newline
393 | \uncheckbox Simulation \\ \hline
394 | \end{tabular}
395 | \end{table}
396 |
397 | \begin{table}
398 | \centering
399 | \caption{Guideline on using the base workspace.}
400 | \label{tbl:guideline4}
401 | \begin{tabular}{|l|p{30em}|}
402 | \hline
403 | ID: Title & 4: Use of the Base Workspace \\ \hline
404 | Priority & Recommended \\ \hline
405 | \Matlab Version & R2006a and later \\ \hline
406 | Description & Do not use the base workspace for storing, reading, or writing data that a model is dependant on. Instead, place such data in either the model workspace, if it is to be used in a single model, or a data dictionary if it is to be shared across models. This means avoiding the use of the sources,
407 | \begin{itemize}
408 | \item \fromfile
409 | \item \fromworkspace
410 | \item \fromspreadsheet
411 | \end{itemize}
412 | and sinks,
413 | \begin{itemize}
414 | \item \tofile
415 | \item \toworkspace
416 | \end{itemize}
417 | as well as avoiding defining signals, types, \etc in the base workspace. \\ \hline
418 | Rationale & \checkbox Readability \newline
419 | \checkbox Verification and Validation \newline
420 | \checkbox Workflow \newline
421 | \checkbox Code Generation \newline
422 | \checkbox Simulation \\ \hline
423 | \end{tabular}
424 | \end{table}
425 |
426 | %-------------------------
427 | \subsubsection{\menu{5} and \menu{6}}
428 | %-------------------------
429 | \emph{Note: This option is not available in versions prior to R2016a.}
430 |
431 | Right-clicking anywhere in the model and then hovering over \cmd{\menu{5}} or \cmd{\menu{6}} from the Context Menu will give the user options to insert the interface representation in the model (\eg Figure~\ref{FIG:interface_visual}), or print the interface description to the Command Window (\eg Figure~\ref{FIG:interface_text}).
432 |
433 | \begin{figure}[htb]
434 | \begin{subfigure}[b]{.6\textwidth}
435 | \includegraphics[height=1.4\textwidth]{../figs/Interface}
436 | \caption{Visual representation.}
437 | \label{FIG:interface_visual}
438 | \end{subfigure}
439 | \begin{subfigure}[b]{.4\textwidth}
440 | \lstset{basicstyle=\footnotesize\ttfamily, keepspaces=false, columns=flexible,}
441 | \begin{lstlisting}
442 | Inputs
443 | ------
444 | Inports:
445 | Demo/In1, uint16, 1, 1
446 |
447 | Outputs
448 | -------
449 | Outports:
450 | Demo/Out1, Inherit: auto, 1, 1
451 | Demo/Out2, Inherit: auto, -1, 1
452 | Demo/Out3, Inherit: auto, -1, Inf
453 | To Files:
454 | Demo/To File1, Timeseries, N/A, 1
455 | Demo/To File2, Timeseries, N/A, 1
456 | Data Store Writes:
457 | Demo/Data Store Write, uint16, 1, 1
458 |
459 | Exports
460 | -------
461 | Simulink Functions:
462 | Demo/Simulink Function,
463 | In: uint16, 1, -1
464 | Out: uint16, 1, -1
465 | \end{lstlisting}
466 | \caption{Textual description.}
467 | \label{FIG:interface_text}
468 | \end{subfigure}
469 | \caption{\Simulink module interface.}
470 | \label{FIG:simulinkinterface}
471 | \end{figure}
472 |
473 | %-------------------------
474 | \subsubsection{\menu{8}}
475 | %-------------------------
476 | Right-clicking anywhere in the model and then selecting \cmd{\menu{8}} will delete the interface that was created using the \cmd{\menu{5}} option.
477 |
478 | \newpage
479 | %-------------------------
480 | \subsubsection{\menu{7}}
481 | %-------------------------
482 | Right-clicking anywhere in the model and then selecting \cmd{\menu{7}} from the Context Menus will print the dependencies that the model relies on in the Command Window. Dependencies include: \modelref blocks, \library blocks, and data dictionaries. An example of the output is shown in Figure~\ref{FIG:dependencies}.
483 |
484 | \begin{figure}[htb]
485 | \centering
486 | \lstset{basicstyle=\footnotesize\ttfamily, keepspaces=false, columns=flexible,}
487 | \begin{lstlisting}
488 | Model References
489 | ------
490 | Demo2/ControlModel
491 | Demo2/Subsystem/EstimationModel
492 |
493 | Library Links
494 | ------
495 | Demo2/Subsystem2/CustomTable
496 |
497 | Data Dictionaries
498 | ------
499 | definitions.sldd
500 | \end{lstlisting}
501 | \caption{List of dependencies.}
502 | \label{FIG:dependencies}
503 | \end{figure}
504 |
505 | %---------------------------------------
506 | % What else does the tool do?
507 | %---------------------------------------
508 |
509 | \subsection{Errors and Warnings}
510 | Any errors or warnings during tool use will be visible in the \matlab Command Window or as pop-up windows.
511 |
512 | \begin{enumerate}
513 |
514 |
515 | \item If a \simfunc is moved and one or more \simfunccaller{s} with the same prototype exist within its previous scope, a warning will appear in the Command Window. It is recommended that the user ensure all \simfunccaller{s} still correctly call the \simfunc. Automatic updating of \simfunccaller blocks is planned for a future version of this tool.
516 | \end{enumerate}
517 |
518 | \subsection{Limitations}
519 | A \Simulink model can depend on or interact with other files and elements via the use of Callbacks\footnote{\url{https://www.mathworks.com/help/simulink/ug/model-callbacks.html}} and S-Functions\footnote{\url{https://www.mathworks.com/help/simulink/sfg/what-is-an-s-function.html}}. Identifying these is not currently supported by the tool.
520 |
521 | \begin{thebibliography}{9}
522 | \bibitem{paper}
523 | Monika Jaskolka, Vera Pantelic, Alan Wassyng, and Mark Lawford, ``Supporting Modularity in \Simulink Models", \emph{arXiv:2007.10120}.
524 | \end{thebibliography}
525 |
526 | \end{document}
--------------------------------------------------------------------------------
/example/Demo.mdl:
--------------------------------------------------------------------------------
1 | Model {
2 | Name "Demo2"
3 | Version 8.4
4 | SavedCharacterEncoding "windows-1252"
5 | GraphicalInterface {
6 | NumRootInports 1
7 | Inport {
8 | Name "In1"
9 | BusObject ""
10 | }
11 | NumRootOutports 3
12 | Outport {
13 | Name "Out1"
14 | BusObject ""
15 | BusOutputAsStruct "off"
16 | }
17 | Outport {
18 | Name "Out2"
19 | BusObject ""
20 | BusOutputAsStruct "off"
21 | }
22 | Outport {
23 | Name "Out3"
24 | BusObject ""
25 | BusOutputAsStruct "off"
26 | }
27 | ParameterArgumentNames ""
28 | ComputedModelVersion "1.101"
29 | NumModelReferences 1
30 | ModelReference {
31 | ModelRefBlockPath "Demo2/Model|sl_subsys_for1"
32 | }
33 | NumTestPointedSignals 0
34 | }
35 | PreLoadFcn "DataStore = Simulink.Signal;\nDataStore.Description = 'Stores data for demo.';\nDataStore.DataType = "
36 | "'uint16';\nDataStore.Complexity = 'real';\nDataStore.Dimensions = 1;\nDataStore.SamplingMode='Sample based';\nDataSt"
37 | "ore.SampleTime = 1;"
38 | ScopeRefreshTime 0.035000
39 | OverrideScopeRefreshTime on
40 | DisableAllScopes off
41 | DataTypeOverride "UseLocalSettings"
42 | DataTypeOverrideAppliesTo "AllNumericTypes"
43 | MinMaxOverflowLogging "UseLocalSettings"
44 | MinMaxOverflowArchiveMode "Overwrite"
45 | FPTRunName "Run 1"
46 | MaxMDLFileLineLength 120
47 | Object {
48 | $PropName "BdWindowsInfo"
49 | $ObjectID 1
50 | $ClassName "Simulink.BDWindowsInfo"
51 | Object {
52 | $PropName "WindowsInfo"
53 | $ObjectID 2
54 | $ClassName "Simulink.WindowInfo"
55 | IsActive [1]
56 | Location [463.0, 145.0, 987.0, 945.0]
57 | Object {
58 | $PropName "ModelBrowserInfo"
59 | $ObjectID 3
60 | $ClassName "Simulink.ModelBrowserInfo"
61 | Visible [0]
62 | DockPosition "Left"
63 | Width [50]
64 | Height [50]
65 | Filter [9]
66 | }
67 | Object {
68 | $PropName "ExplorerBarInfo"
69 | $ObjectID 4
70 | $ClassName "Simulink.ExplorerBarInfo"
71 | Visible [1]
72 | }
73 | Object {
74 | $PropName "EditorsInfo"
75 | $ObjectID 5
76 | $ClassName "Simulink.EditorInfo"
77 | IsActive [1]
78 | ViewObjType "SimulinkTopLevel"
79 | LoadSaveID "0"
80 | Extents [933.0, 765.0]
81 | ZoomFactor [1.9293193717277484]
82 | Offset [78.464395537136454, 6.7435549525101521]
83 | }
84 | }
85 | }
86 | Created "Tue Apr 16 13:02:10 2019"
87 | Creator "monika"
88 | UpdateHistory "UpdateHistoryNever"
89 | ModifiedByFormat "%"
90 | LastModifiedBy "monika"
91 | ModifiedDateFormat "%"
92 | LastModifiedDate "Mon Apr 29 22:59:11 2019"
93 | RTWModifiedTimeStamp 478479551
94 | ModelVersionFormat "1.%"
95 | SampleTimeColors off
96 | SampleTimeAnnotations off
97 | LibraryLinkDisplay "none"
98 | WideLines off
99 | ShowLineDimensions off
100 | ShowPortDataTypes off
101 | ShowDesignRanges off
102 | ShowLoopsOnError on
103 | IgnoreBidirectionalLines off
104 | ShowStorageClass off
105 | ShowTestPointIcons on
106 | ShowSignalResolutionIcons on
107 | ShowViewerIcons on
108 | SortedOrder off
109 | ExecutionContextIcon off
110 | ShowLinearizationAnnotations on
111 | ShowMarkup on
112 | BlockNameDataTip off
113 | BlockParametersDataTip off
114 | BlockDescriptionStringDataTip off
115 | ToolBar on
116 | StatusBar on
117 | BrowserShowLibraryLinks off
118 | BrowserLookUnderMasks off
119 | SimulationMode "normal"
120 | PauseTimes "5"
121 | NumberOfSteps 1
122 | SnapshotBufferSize 10
123 | SnapshotInterval 10
124 | NumberOfLastSnapshots 0
125 | LinearizationMsg "none"
126 | Profile off
127 | ParamWorkspaceSource "MATLABWorkspace"
128 | AccelSystemTargetFile "accel.tlc"
129 | AccelTemplateMakefile "accel_default_tmf"
130 | AccelMakeCommand "make_rtw"
131 | TryForcingSFcnDF off
132 | Object {
133 | $PropName "DataLoggingOverride"
134 | $ObjectID 7
135 | $ClassName "Simulink.SimulationData.ModelLoggingInfo"
136 | model_ "Demo2"
137 | Array {
138 | Type "Cell"
139 | Dimension 1
140 | Cell "Demo2"
141 | PropName "logAsSpecifiedByModels_"
142 | }
143 | Array {
144 | Type "Cell"
145 | Dimension 1
146 | Cell ""
147 | PropName "logAsSpecifiedByModelsSSIDs_"
148 | }
149 | }
150 | RecordCoverage off
151 | CovPath "/"
152 | CovSaveName "covdata"
153 | CovMetricSettings "d"
154 | CovNameIncrementing off
155 | CovHtmlReporting on
156 | CovForceBlockReductionOff on
157 | CovEnableCumulative on
158 | covSaveCumulativeToWorkspaceVar on
159 | CovSaveSingleToWorkspaceVar on
160 | CovCumulativeVarName "covCumulativeData"
161 | CovCumulativeReport off
162 | CovReportOnPause on
163 | CovModelRefEnable "Off"
164 | CovExternalEMLEnable off
165 | CovSFcnEnable on
166 | CovBoundaryAbsTol 0.000010
167 | CovBoundaryRelTol 0.010000
168 | CovUseTimeInterval off
169 | CovStartTime 0
170 | CovStopTime 0
171 | ExtModeBatchMode off
172 | ExtModeEnableFloating on
173 | ExtModeTrigType "manual"
174 | ExtModeTrigMode "normal"
175 | ExtModeTrigPort "1"
176 | ExtModeTrigElement "any"
177 | ExtModeTrigDuration 1000
178 | ExtModeTrigDurationFloating "auto"
179 | ExtModeTrigHoldOff 0
180 | ExtModeTrigDelay 0
181 | ExtModeTrigDirection "rising"
182 | ExtModeTrigLevel 0
183 | ExtModeArchiveMode "off"
184 | ExtModeAutoIncOneShot off
185 | ExtModeIncDirWhenArm off
186 | ExtModeAddSuffixToVar off
187 | ExtModeWriteAllDataToWs off
188 | ExtModeArmWhenConnect on
189 | ExtModeSkipDownloadWhenConnect off
190 | ExtModeLogAll on
191 | ExtModeAutoUpdateStatusClock off
192 | ShowModelReferenceBlockVersion off
193 | ShowModelReferenceBlockIO off
194 | Array {
195 | Type "Handle"
196 | Dimension 1
197 | Simulink.ConfigSet {
198 | $ObjectID 8
199 | Version "1.14.3"
200 | Array {
201 | Type "Handle"
202 | Dimension 8
203 | Simulink.SolverCC {
204 | $ObjectID 9
205 | Version "1.14.3"
206 | StartTime "0.0"
207 | StopTime "10.0"
208 | AbsTol "auto"
209 | FixedStep "1"
210 | InitialStep "auto"
211 | MaxOrder 5
212 | ZcThreshold "auto"
213 | ConsecutiveZCsStepRelTol "10*128*eps"
214 | MaxConsecutiveZCs "1000"
215 | ExtrapolationOrder 4
216 | NumberNewtonIterations 1
217 | MaxStep "auto"
218 | MinStep "auto"
219 | MaxConsecutiveMinStep "1"
220 | RelTol "1e-3"
221 | SolverMode "Auto"
222 | EnableConcurrentExecution off
223 | ConcurrentTasks off
224 | Solver "FixedStepDiscrete"
225 | SolverName "FixedStepDiscrete"
226 | SolverJacobianMethodControl "auto"
227 | ShapePreserveControl "DisableAll"
228 | ZeroCrossControl "UseLocalSettings"
229 | ZeroCrossAlgorithm "Nonadaptive"
230 | AlgebraicLoopSolver "TrustRegion"
231 | SolverResetMethod "Fast"
232 | PositivePriorityOrder off
233 | AutoInsertRateTranBlk off
234 | SampleTimeConstraint "Unconstrained"
235 | InsertRTBMode "Whenever possible"
236 | }
237 | Simulink.DataIOCC {
238 | $ObjectID 10
239 | Version "1.14.3"
240 | Decimation "1"
241 | ExternalInput "[t, u]"
242 | FinalStateName "xFinal"
243 | InitialState "xInitial"
244 | LimitDataPoints on
245 | MaxDataPoints "1000"
246 | LoadExternalInput off
247 | LoadInitialState off
248 | SaveFinalState off
249 | SaveCompleteFinalSimState off
250 | SaveFormat "StructureWithTime"
251 | SignalLoggingSaveFormat "Dataset"
252 | SaveOutput on
253 | SaveState off
254 | SignalLogging on
255 | DSMLogging on
256 | InspectSignalLogs off
257 | VisualizeSimOutput on
258 | SaveTime on
259 | ReturnWorkspaceOutputs off
260 | StateSaveName "xout"
261 | TimeSaveName "tout"
262 | OutputSaveName "yout"
263 | SignalLoggingName "logsout"
264 | DSMLoggingName "dsmout"
265 | OutputOption "RefineOutputTimes"
266 | OutputTimes "[]"
267 | ReturnWorkspaceOutputsName "out"
268 | Refine "1"
269 | }
270 | Simulink.OptimizationCC {
271 | $ObjectID 11
272 | Version "1.14.3"
273 | Array {
274 | Type "Cell"
275 | Dimension 8
276 | Cell "ZeroExternalMemoryAtStartup"
277 | Cell "ZeroInternalMemoryAtStartup"
278 | Cell "NoFixptDivByZeroProtection"
279 | Cell "OptimizeModelRefInitCode"
280 | Cell "BooleansAsBitfields"
281 | Cell "PassReuseOutputArgsAs"
282 | Cell "PassReuseOutputArgsThreshold"
283 | Cell "UseSpecifiedMinMax"
284 | PropName "DisabledProps"
285 | }
286 | BlockReduction off
287 | BooleanDataType off
288 | ConditionallyExecuteInputs on
289 | InlineParams off
290 | UseDivisionForNetSlopeComputation "Off"
291 | UseFloatMulNetSlope off
292 | DefaultUnderspecifiedDataType "double"
293 | UseSpecifiedMinMax off
294 | InlineInvariantSignals off
295 | OptimizeBlockIOStorage on
296 | BufferReuse on
297 | EnhancedBackFolding off
298 | CachingGlobalReferences off
299 | GlobalBufferReuse on
300 | StrengthReduction off
301 | ExpressionFolding on
302 | BooleansAsBitfields off
303 | BitfieldContainerType "uint_T"
304 | EnableMemcpy on
305 | MemcpyThreshold 64
306 | PassReuseOutputArgsAs "Structure reference"
307 | ExpressionDepthLimit 2147483647
308 | LocalBlockOutputs on
309 | RollThreshold 5
310 | StateBitsets off
311 | DataBitsets off
312 | ActiveStateOutputEnumStorageType "Native Integer"
313 | ZeroExternalMemoryAtStartup on
314 | ZeroInternalMemoryAtStartup on
315 | InitFltsAndDblsToZero on
316 | NoFixptDivByZeroProtection off
317 | EfficientFloat2IntCast off
318 | EfficientMapNaN2IntZero on
319 | OptimizeModelRefInitCode off
320 | LifeSpan "inf"
321 | MaxStackSize "Inherit from target"
322 | BufferReusableBoundary on
323 | SimCompilerOptimization "Off"
324 | AccelVerboseBuild off
325 | }
326 | Simulink.DebuggingCC {
327 | $ObjectID 12
328 | Version "1.14.3"
329 | RTPrefix "error"
330 | ConsistencyChecking "none"
331 | ArrayBoundsChecking "none"
332 | SignalInfNanChecking "none"
333 | SignalRangeChecking "none"
334 | ReadBeforeWriteMsg "UseLocalSettings"
335 | WriteAfterWriteMsg "UseLocalSettings"
336 | WriteAfterReadMsg "UseLocalSettings"
337 | AlgebraicLoopMsg "warning"
338 | ArtificialAlgebraicLoopMsg "warning"
339 | SaveWithDisabledLinksMsg "warning"
340 | SaveWithParameterizedLinksMsg "none"
341 | CheckSSInitialOutputMsg on
342 | UnderspecifiedInitializationDetection "Simplified"
343 | MergeDetectMultiDrivingBlocksExec "error"
344 | CheckExecutionContextPreStartOutputMsg off
345 | CheckExecutionContextRuntimeOutputMsg off
346 | SignalResolutionControl "TryResolveAllWithWarning"
347 | BlockPriorityViolationMsg "warning"
348 | MinStepSizeMsg "warning"
349 | TimeAdjustmentMsg "none"
350 | MaxConsecutiveZCsMsg "error"
351 | MaskedZcDiagnostic "warning"
352 | IgnoredZcDiagnostic "warning"
353 | SolverPrmCheckMsg "none"
354 | InheritedTsInSrcMsg "warning"
355 | MultiTaskDSMMsg "warning"
356 | MultiTaskCondExecSysMsg "none"
357 | MultiTaskRateTransMsg "error"
358 | SingleTaskRateTransMsg "none"
359 | TasksWithSamePriorityMsg "warning"
360 | SigSpecEnsureSampleTimeMsg "warning"
361 | CheckMatrixSingularityMsg "none"
362 | IntegerOverflowMsg "warning"
363 | Int32ToFloatConvMsg "warning"
364 | ParameterDowncastMsg "error"
365 | ParameterOverflowMsg "error"
366 | ParameterUnderflowMsg "none"
367 | ParameterPrecisionLossMsg "warning"
368 | ParameterTunabilityLossMsg "warning"
369 | FixptConstUnderflowMsg "none"
370 | FixptConstOverflowMsg "none"
371 | FixptConstPrecisionLossMsg "none"
372 | UnderSpecifiedDataTypeMsg "none"
373 | UnnecessaryDatatypeConvMsg "none"
374 | VectorMatrixConversionMsg "none"
375 | InvalidFcnCallConnMsg "error"
376 | FcnCallInpInsideContextMsg "EnableAllAsWarning"
377 | SignalLabelMismatchMsg "none"
378 | UnconnectedInputMsg "warning"
379 | UnconnectedOutputMsg "warning"
380 | UnconnectedLineMsg "warning"
381 | SFcnCompatibilityMsg "none"
382 | FrameProcessingCompatibilityMsg "error"
383 | UniqueDataStoreMsg "none"
384 | BusObjectLabelMismatch "warning"
385 | RootOutportRequireBusObject "warning"
386 | AssertControl "UseLocalSettings"
387 | ModelReferenceIOMsg "none"
388 | ModelReferenceMultiInstanceNormalModeStructChecksumCheck "error"
389 | ModelReferenceVersionMismatchMessage "none"
390 | ModelReferenceIOMismatchMessage "none"
391 | UnknownTsInhSupMsg "warning"
392 | ModelReferenceDataLoggingMessage "warning"
393 | ModelReferenceSymbolNameMessage "warning"
394 | ModelReferenceExtraNoncontSigs "error"
395 | StateNameClashWarn "warning"
396 | SimStateInterfaceChecksumMismatchMsg "warning"
397 | SimStateOlderReleaseMsg "error"
398 | InitInArrayFormatMsg "warning"
399 | StrictBusMsg "ErrorLevel1"
400 | BusNameAdapt "WarnAndRepair"
401 | NonBusSignalsTreatedAsBus "none"
402 | BlockIODiagnostic "none"
403 | SFUnusedDataAndEventsDiag "warning"
404 | SFUnexpectedBacktrackingDiag "warning"
405 | SFInvalidInputDataAccessInChartInitDiag "warning"
406 | SFNoUnconditionalDefaultTransitionDiag "warning"
407 | SFTransitionOutsideNaturalParentDiag "warning"
408 | SFUnconditionalTransitionShadowingDiag "warning"
409 | SFUndirectedBroadcastEventsDiag "warning"
410 | SFTransitionActionBeforeConditionDiag "warning"
411 | IntegerSaturationMsg "warning"
412 | ModelReferenceCSMismatchMessage "none"
413 | }
414 | Simulink.HardwareCC {
415 | $ObjectID 13
416 | Version "1.14.3"
417 | ProdBitPerChar 8
418 | ProdBitPerShort 16
419 | ProdBitPerInt 32
420 | ProdBitPerLong 32
421 | ProdBitPerLongLong 64
422 | ProdBitPerFloat 32
423 | ProdBitPerDouble 64
424 | ProdBitPerPointer 32
425 | ProdLargestAtomicInteger "Char"
426 | ProdLargestAtomicFloat "None"
427 | ProdIntDivRoundTo "Undefined"
428 | ProdEndianess "Unspecified"
429 | ProdWordSize 32
430 | ProdShiftRightIntArith on
431 | ProdLongLongMode off
432 | ProdHWDeviceType "32-bit Generic"
433 | TargetBitPerChar 8
434 | TargetBitPerShort 16
435 | TargetBitPerInt 32
436 | TargetBitPerLong 32
437 | TargetBitPerLongLong 64
438 | TargetBitPerFloat 32
439 | TargetBitPerDouble 64
440 | TargetBitPerPointer 32
441 | TargetLargestAtomicInteger "Char"
442 | TargetLargestAtomicFloat "None"
443 | TargetShiftRightIntArith on
444 | TargetLongLongMode off
445 | TargetIntDivRoundTo "Undefined"
446 | TargetEndianess "Unspecified"
447 | TargetWordSize 32
448 | TargetPreprocMaxBitsSint 32
449 | TargetPreprocMaxBitsUint 32
450 | TargetHWDeviceType "Specified"
451 | TargetUnknown on
452 | ProdEqTarget on
453 | }
454 | Simulink.ModelReferenceCC {
455 | $ObjectID 14
456 | Version "1.14.3"
457 | UpdateModelReferenceTargets "IfOutOfDateOrStructuralChange"
458 | CheckModelReferenceTargetMessage "error"
459 | EnableParallelModelReferenceBuilds off
460 | ParallelModelReferenceErrorOnInvalidPool on
461 | ParallelModelReferenceMATLABWorkerInit "None"
462 | ModelReferenceNumInstancesAllowed "Multi"
463 | PropagateVarSize "Infer from blocks in model"
464 | ModelReferencePassRootInputsByReference on
465 | ModelReferenceMinAlgLoopOccurrences off
466 | PropagateSignalLabelsOutOfModel off
467 | SupportModelReferenceSimTargetCustomCode off
468 | }
469 | Simulink.SFSimCC {
470 | $ObjectID 15
471 | Version "1.14.3"
472 | SFSimEcho on
473 | SimCtrlC on
474 | SimIntegrity on
475 | SimUseLocalCustomCode off
476 | SimParseCustomCode on
477 | SimBuildMode "sf_incremental_build"
478 | SimGenImportedTypeDefs off
479 | }
480 | Simulink.RTWCC {
481 | $BackupClass "Simulink.RTWCC"
482 | $ObjectID 16
483 | Version "1.14.3"
484 | Array {
485 | Type "Cell"
486 | Dimension 16
487 | Cell "IncludeHyperlinkInReport"
488 | Cell "GenerateTraceInfo"
489 | Cell "GenerateTraceReport"
490 | Cell "GenerateTraceReportSl"
491 | Cell "GenerateTraceReportSf"
492 | Cell "GenerateTraceReportEml"
493 | Cell "PortableWordSizes"
494 | Cell "GenerateWebview"
495 | Cell "GenerateCodeMetricsReport"
496 | Cell "GenerateCodeReplacementReport"
497 | Cell "GenerateMissedCodeReplacementReport"
498 | Cell "GenerateErtSFunction"
499 | Cell "CreateSILPILBlock"
500 | Cell "CodeExecutionProfiling"
501 | Cell "CodeProfilingSaveOptions"
502 | Cell "CodeProfilingInstrumentation"
503 | PropName "DisabledProps"
504 | }
505 | SystemTargetFile "grt.tlc"
506 | TLCOptions ""
507 | GenCodeOnly off
508 | MakeCommand "make_rtw"
509 | GenerateMakefile on
510 | PackageGeneratedCodeAndArtifacts off
511 | TemplateMakefile "grt_default_tmf"
512 | PostCodeGenCommand ""
513 | GenerateReport off
514 | RTWVerbose on
515 | RetainRTWFile off
516 | ProfileTLC off
517 | TLCDebug off
518 | TLCCoverage off
519 | TLCAssert off
520 | RTWUseLocalCustomCode off
521 | RTWUseSimCustomCode off
522 | Toolchain "Automatically locate an installed toolchain"
523 | BuildConfiguration "Faster Builds"
524 | IncludeHyperlinkInReport off
525 | LaunchReport off
526 | PortableWordSizes off
527 | CreateSILPILBlock "None"
528 | CodeExecutionProfiling off
529 | CodeExecutionProfileVariable "executionProfile"
530 | CodeProfilingSaveOptions "SummaryOnly"
531 | CodeProfilingInstrumentation off
532 | SILDebugging off
533 | TargetLang "C"
534 | IncludeBusHierarchyInRTWFileBlockHierarchyMap off
535 | GenerateTraceInfo off
536 | GenerateTraceReport off
537 | GenerateTraceReportSl off
538 | GenerateTraceReportSf off
539 | GenerateTraceReportEml off
540 | GenerateWebview off
541 | GenerateCodeMetricsReport off
542 | GenerateCodeReplacementReport off
543 | RTWCompilerOptimization "Off"
544 | RTWCustomCompilerOptimizations ""
545 | CheckMdlBeforeBuild "Off"
546 | SharedConstantsCachingThreshold 1024
547 | Array {
548 | Type "Handle"
549 | Dimension 2
550 | Simulink.CodeAppCC {
551 | $ObjectID 17
552 | Version "1.14.3"
553 | Array {
554 | Type "Cell"
555 | Dimension 28
556 | Cell "IgnoreCustomStorageClasses"
557 | Cell "InsertBlockDesc"
558 | Cell "SFDataObjDesc"
559 | Cell "SimulinkDataObjDesc"
560 | Cell "DefineNamingRule"
561 | Cell "SignalNamingRule"
562 | Cell "ParamNamingRule"
563 | Cell "InlinedPrmAccess"
564 | Cell "CustomSymbolStr"
565 | Cell "IgnoreTestpoints"
566 | Cell "InsertPolySpaceComments"
567 | Cell "MATLABFcnDesc"
568 | Cell "InternalIdentifier"
569 | Cell "CustomSymbolStrGlobalVar"
570 | Cell "CustomSymbolStrType"
571 | Cell "CustomSymbolStrField"
572 | Cell "CustomSymbolStrFcn"
573 | Cell "CustomSymbolStrModelFcn"
574 | Cell "CustomSymbolStrFcnArg"
575 | Cell "CustomSymbolStrBlkIO"
576 | Cell "CustomSymbolStrTmpVar"
577 | Cell "CustomSymbolStrMacro"
578 | Cell "CustomSymbolStrUtil"
579 | Cell "CustomSymbolStrEmxType"
580 | Cell "CustomSymbolStrEmxFcn"
581 | Cell "CustomUserTokenString"
582 | Cell "ReqsInCode"
583 | Cell "BlockCommentType"
584 | PropName "DisabledProps"
585 | }
586 | ForceParamTrailComments off
587 | GenerateComments on
588 | CommentStyle "Auto"
589 | IgnoreCustomStorageClasses on
590 | IgnoreTestpoints off
591 | MaxIdLength 31
592 | PreserveName off
593 | PreserveNameWithParent off
594 | ShowEliminatedStatement on
595 | OperatorAnnotations off
596 | SimulinkDataObjDesc off
597 | SFDataObjDesc off
598 | MATLABFcnDesc off
599 | MangleLength 1
600 | CustomSymbolStrGlobalVar "$R$N$M"
601 | CustomSymbolStrType "$N$R$M_T"
602 | CustomSymbolStrField "$N$M"
603 | CustomSymbolStrFcn "$R$N$M$F"
604 | CustomSymbolStrFcnArg "rt$I$N$M"
605 | CustomSymbolStrBlkIO "rtb_$N$M"
606 | CustomSymbolStrTmpVar "$N$M"
607 | CustomSymbolStrMacro "$R$N$M"
608 | CustomSymbolStrUtil "$N$C"
609 | DefineNamingRule "None"
610 | ParamNamingRule "None"
611 | SignalNamingRule "None"
612 | InsertBlockDesc off
613 | InsertPolySpaceComments off
614 | SimulinkBlockComments on
615 | MATLABSourceComments off
616 | EnableCustomComments off
617 | InternalIdentifier "Shortened"
618 | InlinedPrmAccess "Literals"
619 | ReqsInCode off
620 | UseSimReservedNames off
621 | }
622 | Simulink.GRTTargetCC {
623 | $BackupClass "Simulink.TargetCC"
624 | $ObjectID 18
625 | Version "1.14.3"
626 | Array {
627 | Type "Cell"
628 | Dimension 17
629 | Cell "IncludeMdlTerminateFcn"
630 | Cell "RemoveResetFunc"
631 | Cell "SuppressErrorStatus"
632 | Cell "ERTCustomFileBanners"
633 | Cell "GenerateSampleERTMain"
634 | Cell "MultiInstanceERTCode"
635 | Cell "PurelyIntegerCode"
636 | Cell "SupportNonInlinedSFcns"
637 | Cell "SupportComplex"
638 | Cell "SupportAbsoluteTime"
639 | Cell "SupportContinuousTime"
640 | Cell "ExistingSharedCode"
641 | Cell "GenerateTestInterfaces"
642 | Cell "ModelStepFunctionPrototypeControlCompliant"
643 | Cell "GenerateAllocFcn"
644 | Cell "RemoveDisableFunc"
645 | Cell "PreserveStateflowLocalDataDimensions"
646 | PropName "DisabledProps"
647 | }
648 | TargetFcnLib "ansi_tfl_tmw.mat"
649 | TargetLibSuffix ""
650 | TargetPreCompLibLocation ""
651 | GenFloatMathFcnCalls "NOT IN USE"
652 | TargetLangStandard "C89/C90 (ANSI)"
653 | CodeReplacementLibrary "None"
654 | UtilityFuncGeneration "Auto"
655 | ERTMultiwordTypeDef "System defined"
656 | MultiwordLength 2048
657 | GenerateFullHeader on
658 | GenerateSampleERTMain off
659 | GenerateTestInterfaces off
660 | ModelReferenceCompliant on
661 | ParMdlRefBuildCompliant on
662 | CompOptLevelCompliant on
663 | ConcurrentExecutionCompliant on
664 | IncludeMdlTerminateFcn on
665 | GeneratePreprocessorConditionals "Disable all"
666 | CombineOutputUpdateFcns off
667 | CombineSignalStateStructs off
668 | SuppressErrorStatus off
669 | IncludeFileDelimiter "Auto"
670 | ERTCustomFileBanners off
671 | SupportAbsoluteTime on
672 | LogVarNameModifier "rt_"
673 | MatFileLogging on
674 | MultiInstanceERTCode off
675 | CodeInterfacePackaging "Nonreusable function"
676 | SupportNonFinite on
677 | SupportComplex on
678 | PurelyIntegerCode off
679 | SupportContinuousTime on
680 | SupportNonInlinedSFcns on
681 | SupportVariableSizeSignals off
682 | ParenthesesLevel "Nominal"
683 | CastingMode "Nominal"
684 | MATLABClassNameForMDSCustomization "Simulink.SoftwareTarget.GRTCustomization"
685 | ModelStepFunctionPrototypeControlCompliant off
686 | CPPClassGenCompliant on
687 | AutosarCompliant off
688 | GRTInterface on
689 | GenerateAllocFcn off
690 | GenerateSharedConstants on
691 | UseMalloc off
692 | ExtMode off
693 | ExtModeStaticAlloc off
694 | ExtModeTesting off
695 | ExtModeStaticAllocSize 1000000
696 | ExtModeTransport 0
697 | ExtModeMexFile "ext_comm"
698 | ExtModeIntrfLevel "Level1"
699 | RTWCAPISignals off
700 | RTWCAPIParams off
701 | RTWCAPIStates off
702 | RTWCAPIRootIO off
703 | GenerateASAP2 off
704 | MultiInstanceErrorCode "Error"
705 | }
706 | PropName "Components"
707 | }
708 | }
709 | PropName "Components"
710 | }
711 | Name "Configuration"
712 | ExtraOptions "-aExprFoldComments=1 "
713 | CurrentDlgPage "Data Import//Export"
714 | ConfigPrmDlgPosition [ 338, 291, 1218, 921 ]
715 | }
716 | PropName "ConfigurationSets"
717 | }
718 | Simulink.ConfigSet {
719 | $PropName "ActiveConfigurationSet"
720 | $ObjectID 8
721 | }
722 | Object {
723 | $PropName "DataTransfer"
724 | $ObjectID 20
725 | $ClassName "Simulink.GlobalDataTransfer"
726 | DefaultTransitionBetweenSyncTasks "Ensure deterministic transfer (maximum delay)"
727 | DefaultTransitionBetweenAsyncTasks "Ensure data integrity only"
728 | DefaultTransitionBetweenContTasks "Ensure deterministic transfer (minimum delay)"
729 | DefaultExtrapolationMethodBetweenContTasks "None"
730 | AutoInsertRateTranBlk [0]
731 | }
732 | ExplicitPartitioning off
733 | BlockDefaults {
734 | ForegroundColor "black"
735 | BackgroundColor "white"
736 | DropShadow off
737 | NamePlacement "normal"
738 | FontName "Helvetica"
739 | FontSize 10
740 | FontWeight "normal"
741 | FontAngle "normal"
742 | ShowName on
743 | BlockRotation 0
744 | BlockMirror off
745 | }
746 | AnnotationDefaults {
747 | HorizontalAlignment "center"
748 | VerticalAlignment "middle"
749 | ForegroundColor "black"
750 | BackgroundColor "white"
751 | DropShadow off
752 | FontName "Helvetica"
753 | FontSize 10
754 | FontWeight "normal"
755 | FontAngle "normal"
756 | UseDisplayTextAsClickCallback off
757 | }
758 | LineDefaults {
759 | FontName "Helvetica"
760 | FontSize 9
761 | FontWeight "normal"
762 | FontAngle "normal"
763 | }
764 | MaskDefaults {
765 | SelfModifiable "off"
766 | IconFrame "on"
767 | IconOpaque "on"
768 | RunInitForIconRedraw "off"
769 | IconRotate "none"
770 | PortRotate "default"
771 | IconUnits "autoscale"
772 | }
773 | MaskParameterDefaults {
774 | Evaluate "on"
775 | Tunable "on"
776 | NeverSave "off"
777 | Internal "off"
778 | ReadOnly "off"
779 | Enabled "on"
780 | Visible "on"
781 | ToolTip "on"
782 | }
783 | BlockParameterDefaults {
784 | Block {
785 | BlockType ArgIn
786 | Port "1"
787 | OutMin "[]"
788 | OutMax "[]"
789 | OutDataTypeStr "double"
790 | LockScale off
791 | PortDimensions "1"
792 | SignalType "real"
793 | }
794 | Block {
795 | BlockType ArgOut
796 | Port "1"
797 | OutMin "[]"
798 | OutMax "[]"
799 | OutDataTypeStr "double"
800 | LockScale off
801 | PortDimensions "1"
802 | SignalType "real"
803 | }
804 | Block {
805 | BlockType Constant
806 | Value "1"
807 | VectorParams1D on
808 | SamplingMode "Sample based"
809 | OutMin "[]"
810 | OutMax "[]"
811 | OutDataTypeStr "Inherit: Inherit from 'Constant value'"
812 | LockScale off
813 | SampleTime "inf"
814 | FramePeriod "inf"
815 | PreserveConstantTs off
816 | }
817 | Block {
818 | BlockType DataStoreWrite
819 | DataStoreName "A"
820 | SampleTime "-1"
821 | }
822 | Block {
823 | BlockType FunctionCaller
824 | FunctionPrototype "y=f(x)"
825 | InputArgumentSpecifications ""
826 | OutputArgumentSpecifications ""
827 | SampleTime "-1"
828 | }
829 | Block {
830 | BlockType Inport
831 | Port "1"
832 | OutputFunctionCall off
833 | OutMin "[]"
834 | OutMax "[]"
835 | OutDataTypeStr "Inherit: auto"
836 | LockScale off
837 | BusOutputAsStruct off
838 | PortDimensions "-1"
839 | VarSizeSig "Inherit"
840 | SampleTime "-1"
841 | SignalType "auto"
842 | SamplingMode "auto"
843 | LatchByDelayingOutsideSignal off
844 | LatchInputForFeedbackSignals off
845 | Interpolate on
846 | }
847 | Block {
848 | BlockType ModelReference
849 | ModelNameDialog ""
850 | SimulationMode "Accelerator"
851 | CodeUnderTest "Model reference"
852 | Variant off
853 | GeneratePreprocessorConditionals off
854 | ContentPreviewEnabled off
855 | CopyOfModelProtected off
856 | CopyOfModelName "sl_subsys_for1"
857 | }
858 | Block {
859 | BlockType Outport
860 | Port "1"
861 | OutMin "[]"
862 | OutMax "[]"
863 | OutDataTypeStr "Inherit: auto"
864 | LockScale off
865 | BusOutputAsStruct off
866 | PortDimensions "-1"
867 | VarSizeSig "Inherit"
868 | SampleTime "-1"
869 | SignalType "auto"
870 | SamplingMode "auto"
871 | SourceOfInitialOutputValue "Dialog"
872 | OutputWhenDisabled "held"
873 | InitialOutput "[]"
874 | OutputWhenUnConnected off
875 | }
876 | Block {
877 | BlockType Product
878 | Inputs "2"
879 | Multiplication "Element-wise(.*)"
880 | CollapseMode "All dimensions"
881 | CollapseDim "1"
882 | InputSameDT on
883 | OutMin "[]"
884 | OutMax "[]"
885 | OutDataTypeStr "Inherit: Same as first input"
886 | LockScale off
887 | RndMeth "Zero"
888 | SaturateOnIntegerOverflow on
889 | SampleTime "-1"
890 | }
891 | Block {
892 | BlockType SubSystem
893 | ShowPortLabels "FromPortIcon"
894 | Permissions "ReadWrite"
895 | PermitHierarchicalResolution "All"
896 | TreatAsAtomicUnit off
897 | MinAlgLoopOccurrences off
898 | PropExecContextOutsideSubsystem off
899 | SystemSampleTime "-1"
900 | RTWSystemCode "Auto"
901 | RTWFcnNameOpts "Auto"
902 | RTWFileNameOpts "Auto"
903 | FunctionInterfaceSpec "void_void"
904 | FunctionWithSeparateData off
905 | RTWMemSecFuncInitTerm "Inherit from model"
906 | RTWMemSecFuncExecute "Inherit from model"
907 | RTWMemSecDataConstants "Inherit from model"
908 | RTWMemSecDataInternal "Inherit from model"
909 | RTWMemSecDataParameters "Inherit from model"
910 | SimViewingDevice off
911 | DataTypeOverride "UseLocalSettings"
912 | DataTypeOverrideAppliesTo "AllNumericTypes"
913 | MinMaxOverflowLogging "UseLocalSettings"
914 | Opaque off
915 | MaskHideContents off
916 | SFBlockType "NONE"
917 | Variant off
918 | GeneratePreprocessorConditionals off
919 | ContentPreviewEnabled off
920 | }
921 | Block {
922 | BlockType Sum
923 | IconShape "rectangular"
924 | Inputs "++"
925 | CollapseMode "All dimensions"
926 | CollapseDim "1"
927 | InputSameDT on
928 | AccumDataTypeStr "Inherit: Inherit via internal rule"
929 | OutMin "[]"
930 | OutMax "[]"
931 | OutDataTypeStr "Inherit: Same as first input"
932 | LockScale off
933 | RndMeth "Floor"
934 | SaturateOnIntegerOverflow on
935 | SampleTime "-1"
936 | }
937 | Block {
938 | BlockType ToFile
939 | Filename "untitled.mat"
940 | MatrixName "ans"
941 | SaveFormat "Array"
942 | Decimation "1"
943 | SampleTime "-1"
944 | }
945 | Block {
946 | BlockType TriggerPort
947 | TriggerType "rising"
948 | IsSimulinkFunction off
949 | StatesWhenEnabling "inherit"
950 | PropagateVarSize "During execution"
951 | ShowOutputPort off
952 | OutputDataType "auto"
953 | SampleTimeType "triggered"
954 | SampleTime "1"
955 | ZeroCross on
956 | PortDimensions "-1"
957 | TriggerSignalSampleTime "-1"
958 | OutMin "[]"
959 | OutMax "[]"
960 | OutDataTypeStr "Inherit: auto"
961 | Interpolate on
962 | }
963 | }
964 | System {
965 | Name "Demo2"
966 | Location [463, 145, 1450, 1090]
967 | Open off
968 | ModelBrowserVisibility off
969 | ModelBrowserWidth 200
970 | ScreenColor "white"
971 | PaperOrientation "landscape"
972 | PaperPositionMode "auto"
973 | PaperType "usletter"
974 | PaperUnits "inches"
975 | TiledPaperMargins [0.500000, 0.500000, 0.500000, 0.500000]
976 | TiledPageScale 1
977 | ShowPageBoundaries off
978 | ZoomFactor "193"
979 | ReportName "simulink-default.rpt"
980 | SIDHighWatermark "46"
981 | Block {
982 | BlockType Inport
983 | Name "In1"
984 | SID "46"
985 | Position [155, 133, 185, 147]
986 | ZOrder 335
987 | IconDisplay "Port number"
988 | OutDataTypeStr "uint16"
989 | PortDimensions "1"
990 | SampleTime "1"
991 | }
992 | Block {
993 | BlockType DataStoreWrite
994 | Name "Data Store\nWrite"
995 | SID "41"
996 | Ports [1]
997 | Position [395, 75, 460, 105]
998 | ZOrder 330
999 | DataStoreName "DataStore"
1000 | SampleTime "1"
1001 | }
1002 | Block {
1003 | BlockType FunctionCaller
1004 | Name "Function Caller"
1005 | SID "24"
1006 | Ports [1, 1]
1007 | Position [250, 117, 340, 163]
1008 | ZOrder 323
1009 | FunctionPrototype "y = f(u)"
1010 | InputArgumentSpecifications "uint16(1)"
1011 | OutputArgumentSpecifications "uint16(1)"
1012 | }
1013 | Block {
1014 | BlockType ModelReference
1015 | Name "Model"
1016 | SID "27"
1017 | Ports [0, 2]
1018 | Position [225, 204, 365, 266]
1019 | ZOrder 325
1020 | ModelNameDialog "sl_subsys_for1"
1021 | SimulationMode "Normal"
1022 | ContentPreviewEnabled on
1023 | ModelReferenceVersion "1.66"
1024 | List {
1025 | ListType OutputPortOutputBusAsStructs
1026 | port0 "off"
1027 | port1 "off"
1028 | }
1029 | CopyOfModelName "sl_subsys_for1"
1030 | }
1031 | Block {
1032 | BlockType SubSystem
1033 | Name "Simulink Function"
1034 | SID "19"
1035 | Ports [0, 0, 0, 1]
1036 | Position [245, 32, 345, 74]
1037 | ZOrder 322
1038 | TreatAsAtomicUnit on
1039 | RequestExecContextInheritance off
1040 | ContentPreviewEnabled on
1041 | System {
1042 | Name "Simulink Function"
1043 | Location [258, 83, 1354, 997]
1044 | Open off
1045 | ModelBrowserVisibility off
1046 | ModelBrowserWidth 200
1047 | ScreenColor "white"
1048 | PaperOrientation "landscape"
1049 | PaperPositionMode "auto"
1050 | PaperType "usletter"
1051 | PaperUnits "inches"
1052 | TiledPaperMargins [0.500000, 0.500000, 0.500000, 0.500000]
1053 | TiledPageScale 1
1054 | ShowPageBoundaries off
1055 | ZoomFactor "265"
1056 | Block {
1057 | BlockType TriggerPort
1058 | Name "f"
1059 | SID "20"
1060 | Ports []
1061 | Position [210, 15, 230, 35]
1062 | ZOrder -2
1063 | ForegroundColor [0.078431, 0.380392, 0.305882]
1064 | TriggerType "function-call"
1065 | IsSimulinkFunction on
1066 | FunctionName "f"
1067 | StatesWhenEnabling "held"
1068 | }
1069 | Block {
1070 | BlockType Constant
1071 | Name "Constant1"
1072 | SID "40"
1073 | Position [75, 170, 105, 200]
1074 | ZOrder 9
1075 | OutDataTypeStr "uint16"
1076 | }
1077 | Block {
1078 | BlockType Constant
1079 | Name "Constant2"
1080 | SID "33"
1081 | Position [75, 220, 105, 250]
1082 | ZOrder 5
1083 | Value "2"
1084 | OutDataTypeStr "uint16"
1085 | }
1086 | Block {
1087 | BlockType Product
1088 | Name "Product"
1089 | SID "34"
1090 | Ports [3, 1]
1091 | Position [295, 49, 330, 271]
1092 | ZOrder 6
1093 | Inputs "**/"
1094 | InputSameDT off
1095 | OutDataTypeStr "uint16"
1096 | RndMeth "Floor"
1097 | SaturateOnIntegerOverflow off
1098 | }
1099 | Block {
1100 | BlockType Sum
1101 | Name "Sum"
1102 | SID "39"
1103 | Ports [2, 1]
1104 | Position [185, 150, 205, 170]
1105 | ZOrder 8
1106 | ShowName off
1107 | IconShape "round"
1108 | Inputs "|++"
1109 | InputSameDT off
1110 | OutDataTypeStr "Inherit: Inherit via internal rule"
1111 | SaturateOnIntegerOverflow off
1112 | }
1113 | Block {
1114 | BlockType ArgIn
1115 | Name "ArgIn1"
1116 | SID "21"
1117 | Position [70, 75, 110, 95]
1118 | ZOrder -4
1119 | DisableCoverage on
1120 | OutDataTypeStr "uint16"
1121 | ArgumentName "u"
1122 | }
1123 | Block {
1124 | BlockType ArgOut
1125 | Name "ArgOut1"
1126 | SID "22"
1127 | Position [385, 150, 425, 170]
1128 | ZOrder -5
1129 | DisableCoverage on
1130 | OutDataTypeStr "uint16"
1131 | ArgumentName "y"
1132 | }
1133 | Line {
1134 | ZOrder 16
1135 | SrcBlock "Product"
1136 | SrcPort 1
1137 | DstBlock "ArgOut1"
1138 | DstPort 1
1139 | }
1140 | Line {
1141 | ZOrder 28
1142 | SrcBlock "Constant2"
1143 | SrcPort 1
1144 | DstBlock "Product"
1145 | DstPort 3
1146 | }
1147 | Line {
1148 | ZOrder 41
1149 | SrcBlock "Sum"
1150 | SrcPort 1
1151 | DstBlock "Product"
1152 | DstPort 2
1153 | }
1154 | Line {
1155 | ZOrder 37
1156 | SrcBlock "ArgIn1"
1157 | SrcPort 1
1158 | Points [36, 0]
1159 | Branch {
1160 | ZOrder 47
1161 | Points [0, 75]
1162 | DstBlock "Sum"
1163 | DstPort 1
1164 | }
1165 | Branch {
1166 | ZOrder 38
1167 | DstBlock "Product"
1168 | DstPort 1
1169 | }
1170 | }
1171 | Line {
1172 | ZOrder 40
1173 | SrcBlock "Constant1"
1174 | SrcPort 1
1175 | DstBlock "Sum"
1176 | DstPort 2
1177 | }
1178 | Annotation {
1179 | SID "35"
1180 | Name "\n