MATLAB Requirements Toolbox — Requirements & Traceability
This skill covers everything in the slreq API: creating and reading requirements, managing traceability links, checking verification coverage, allocating requirements to architecture components, and auditing link health.
For architecture phases (System Composer models, functional decomposition, functional→physical allocation) see the mbse-architecture skill.
See references/api-quickref.md in this skill folder for a compact one-page API reference.
The Two File Types
| Extension | Class | Role | |---|---|---| | .slreqx | slreq.ReqSet | Stores requirements (text, hierarchy) | | .slmx | slreq.LinkSet | Stores traceability links outgoing from a source artifact |
When a .slmx file is created
slreq writes a .slmx file only when its companion artifact is the source of at least one link. The LinkSet is keyed on the source artifact, not the destination.
MyReqs~slreqx.slmxappears only if some link's source is a requirement inMyReqs.slreqx(e.g.,slreq.createLink(srcReq, destReq)wheresrcReqlives inMyReqs)MyModel~mdl.slmxappears only if some link's source is a model element inMyModel.slx(typical:slreq.createLink(component, req)with TypeImplement— the component is the source)
An artifact that is only ever a link destination never gets a paired .slmx. In a typical MBSE project:
| Artifact | Gets a .slmx? | Why | |---|---|---| | StakeholderNeeds.slreqx | Yes | SNs are the source of Derive links to SRs | | SystemRequirements.slreqx | Usually no | SRs are destinations of Derive / Implement / Verify links; no file unless SR-to-SR Refine links or links to external docs are added | | TestCases.slreqx | Yes | TC requirements are the source of Verify links to SRs | | Architecture .slx models | Yes | Components are the source of Implement links to SRs |
Reporting rules for build scripts
Because .slmx files are conditional, never claim a .slmx was produced based on the API calls you made — always verify with isfile before reporting. A script that creates only SN→SR Derive links will produce StakeholderNeeds~slreqx.slmx but not SystemRequirements~slreqx.slmx, even though both .slreqx files exist.
Idempotent cleanup and project registration for .slmx files must both guard with isfile:
if isfile(snLinks), delete(snLinks); end % cleanup — safe whether or not it exists
The registerWithProject helper already does this — it skips files that don't exist on disk — so passing a non-existent .slmx path is a no-op, not an error.
Requirements (Phases 1–2)
Two-Level Structure
| Level | ID scheme | Character | |---|---|---| | Stakeholder Needs | SN-SYS-001 | Operational, informal — what the user/operator needs | | System Requirements | SR-SYS-001 | Formal, testable — what the system shall do |
Each SR traces back to one or more SNs via a Derive link.
Well-Formed Shall-Statements
- One obligation per requirement ("shall", not "should" or "will")
- Measurable and testable — include numeric criteria where possible
- Avoid
<and>in Description fields — the Requirements Editor treats them
as HTML. Use "not exceeding", "at least", "greater than", etc.
Good: The system shall respond with latency not exceeding 100 ms. Avoid: The system shall respond with latency < 100 ms.
Creating Requirement Sets
slreq.clear();
if isfile('MyReqs.slreqx'), delete('MyReqs.slreqx'); end
rs = slreq.new('MyReqs.slreqx'); % NOT slreq.createReqSet (does not exist)
req = rs.add();
req.Id = 'SR-SYS-001';
req.Summary = 'Short title';
req.Description = 'The system shall ...';
req.Rationale = 'Why this requirement exists.';
rs.save();
Find a requirement by ID
req = rs.find('Id', 'SR-SYS-001');
Valid Link Types
| Type | Meaning | Direction | |---|---|---| | "Derive" | Parent decomposes into derived child | SN (source) → SR (destination) | | "Implement" | Architecture element (or model block) implements requirement | Component/Block (source) → SR (destination) | | "Verify" | Test case verifies requirement | TC (source) → SR (destination) | | "Refine" | Requirement refined into a more specific requirement (same artifact kind, more detail). Not used for SR → architecture in this workflow. | SR (source) → SR (destination) | | "Relate" | Informal relationship | Bidirectional |
Creating Links
% Req-to-req derivation: parent (e.g. SN) decomposes into derived child (e.g. SR)
lnk = slreq.createLink(parentReq, childReq);
lnk.Type = 'Derive';
% Model block to req (model must be open in Simulink)
lnk = slreq.createLink(blockHandle, req);
lnk.Type = 'Implement';
% Test case requirement to SR
lnk = slreq.createLink(tc, sr);
lnk.Type = 'Verify';
slreq.saveAll(); % always call after creating cross-artifact links
Side effect: {modelName}~mdl.slmx link store
The first time you create a link whose source is an element of a Simulink/System Composer model (component, subsystem, or block), slreq writes a {modelName}~mdl.slmx file next to the .slx. This is the normal case for Implement links in this workflow — slreq.createLink(component, req) has the component as source, so the link lives in the model's LinkSet, not the requirement set's.
A model that only ever receives links (no element of it is used as a link source) does not get a ~mdl.slmx. In MBSE practice this is rare: architecture models almost always have Implement links where they are the source.
After creating links whose source is in a model, register both the .slx and the .slmx with the project, guarding .slmx registration with isfile since the file may not yet exist:
addFile(proj, fullfile(archDir, 'MyModel.slx'));
slmx = fullfile(archDir, 'MyModel~mdl.slmx');
if isfile(slmx), addFile(proj, slmx); end
Forgetting to register an existing .slmx causes project file-system checks to fail and the traceability links won't travel when the project is shared.
Requirements Script Skeleton
See [code/buildMyRequirements.m](code/buildMyRequirements.m) for the full parameterized function:
buildMyRequirements(snFile, srFile)
Exporting a Requirement Set to Excel
There is no public slreq Excel-export API. slreq.export emits ReqIF only, and the Requirements Editor's File → Export → Microsoft Excel is GUI-only. To script an xlsx export, build the table yourself with writetable.
Requirement sets can be hierarchical. find(rs, 'Type', 'Requirement') returns all requirements flat in storage order, which silently drops the parent/child structure the Requirements Editor displays. To preserve hierarchy:
- Find top-level reqs by filtering for
~isa(r.parent(), 'slreq.Requirement')
— top-level items have the ReqSet as their parent, not another requirement
- Recurse via the
children()method (a method, not a property) - Emit rows depth-first so each parent precedes its children
- Sort siblings with a natural sort on the
Indexstring ("1", "1.2", "1.10"
as numeric tuples — lexicographic string sort would put 1.10 before 1.2)
- Write
Index,Depth,ParentIndexcolumns so the hierarchy is recoverable
from the xlsx alone
Note also that r.Id may be an auto-assigned SID like #13 if the set was authored in the Editor without user IDs — always include the Index column as a stable user-meaningful identifier.
Extract parent IDs from incoming Derive links so the DerivedFrom column is populated instead of stuffing parent refs into Rationale:
function ids = deriveParents(req)
ids = strings(0,1);
lnks = req.inLinks();
for k = 1:numel(lnks)
if strcmp(lnks(k).Type, 'Derive')
% getSourceLabel() returns "ID Summary"; strtok pulls just the ID
ids(end+1,1) = string(strtok(