Main Content

Capture Model as Requirements and Create Links

In this step, you use the Requirements Toolbox™ programmatic interface to capture elements from your Simulink® model into a set of proxy slreq.Requirement objects that have the same hierarchy as your model. You can then use the Description and Rationale properties of the proxy requirement objects to document each element of the design. The example also shows how to create links between the model elements and the proxy requirement objects for traceability.

Open the Models

Open the slvnvdemo_powerwindow_vs and slvnvdemo_powerwindowController models. The slvnvdemo_powerwindow_vs model is a specification model that verifies the functional properties of the design in slvnvdemo_powerwindowController.

open_system("slvnvdemo_powerwindow_vs");
open_system("slvnvdemo_powerwindowController");

Capture Model as Proxy Requirements

Use the Requirements Toolbox APIs to capture the Simulink models as proxy slreq.Requirement objects in the Requirements Editor for the slvnvdemo_powerwindow_vs and slvnvdemo_powerwindowController models.

First, create an array with the model names to make it easy to make changes to both models.

models = ["slvnvdemo_powerwindow_vs","slvnvdemo_powerwindowController"];

For each model:

  • Create a requirement set with the same name as the model by using slreq.new.

  • Add an slreq.Requirement object that corresponds to the top-level model by using add.

  • Open the model.

  • Use rmi to get properties for each model element, including the handle, the index of the parent of the model element, an indicator that shows if the element belongs to a Stateflow® chart, and the SID.

for modelIndex = 1:numel(models)
    modelName = models(modelIndex);
    reqSetName = modelName+".slreqx";
    myReqSet = slreq.new(reqSetName);
    topProxy = add(myReqSet,Id=modelName,Summary=modelName+" Description");
    open_system(modelName);
    [elementHandles,parentIndex,isSf,SID] = rmi("getObjectsInModel",modelName);

For each element in the models, get the name and type of the element by using the getNameAndType function. To view the code for this function, see Helper Functions. Add an slreq.Requirement object under the slreq.Requirement object of the parent of the model element in the model hierarchy. Add a summary to the slreq.Requirement object based on the name and type.

    createdProxies(1) = topProxy;
    for elementIndex = 2:numel(elementHandles)
        [name,type] = getNameAndType(isSf(elementIndex),elementHandles(elementIndex), ...
            modelName,SID(elementIndex));
        if ~isempty(name) && ~isempty(type)
    		parentProxy = createdProxies(parentIndex(elementIndex));
            createdProxies(elementIndex) = add(parentProxy,Id=SID{elementIndex}, ...
                Summary=name+" ("+type+")");
    	end
    end
    save(myReqSet);
end

Open the Requirements Editor to view the requirements.

slreq.editor

Requirements Editor showing the created requirements.

Link Requirements and Model Elements

Create links in both the slvnvdemo_powerwindow_vs and slvnvdemo_powerwindowController requirement sets to navigate between the slreq.Requirement object and the corresponding model element.

For each model and its associated requirement set, create an array that contains the requirements.

for modelIndex = 1:numel(models)
    modelName = models(modelIndex);
    reqSetName = slreq.find(Type="ReqSet",Name=modelName);
    proxyRequirements = find(reqSetName,Type="Requirement");

For each requirement in the requirement set other than the top-level requirement:

  • Get the SID of the associated model element and then get a handle to the model element.

  • Create a link between the model element and the requirement.

  • Add a description to the link that includes the index of the linked requirement.

  • Record the number of created links.

    counter = 0;
    for reqIdx = 1:numel(proxyRequirements)
        myProxy = proxyRequirements(reqIdx);
        if ~contains(myProxy.Summary,modelName)
            sid = strcat(modelName,myProxy.Id);
            linkSrc = Simulink.ID.getHandle(sid);
            newLink = slreq.createLink(linkSrc,myProxy);
            newLink.Description = strcat("Link between requirement ",myProxy.Index, ...
                " and model element");
            counter = counter + 1;
        end
    end
    disp(strcat("Created ",num2str(counter)," links for ",modelName));
end
Created 116 links for slvnvdemo_powerwindow_vs
Created 66 links for slvnvdemo_powerwindowController

View the new links in the Requirements Editor by clicking a requirement and, in the right pane, scrolling to the Links section.

A requirement is selected in the Requirements Editor and a link to the associated model element is displayed.Save the link sets.

lsArray = slreq.find(Type="LinkSet");
save(lsArray(1));
save(lsArray(2));

Helper Functions

This function returns the model element name and type. This function skips Stateflow object types other than Stateflow.State and Stateflow.Transition.

function [name,type] = getNameAndType(isSf,elementHandle,modelName,SID)

if ~isSf
    name = get_param(elementHandle,"Name");
    type = get_param(elementHandle,"BlockType");
else
    sfObj = Simulink.ID.getHandle(strcat(modelName,SID));
    sfType = class(sfObj);
    switch sfType
        case 'Stateflow.State'
            name = sf('get',elementHandle,'.name');
            type = strrep(class(sfObj),"Stateflow.","");
        case 'Stateflow.Transition'
            name = sf('get',elementHandle,'.labelString');
            type = strrep(class(sfObj),"Stateflow.","");
        otherwise
            warning('Stateflow object of type %s was skipped.',class(sfObj));
            name = "";
            type = '';
    end
end
end

See Also

Apps

Functions

Related Topics