Generate System Design Reports with Report API
This example shows how to generate a Report API-based system design report. The system design report is a description of the design of a dynamic system generated from the Simulink® model of the system.
A Report API-based system design report uses objects of Report API classes to report on system components. See Create Report Generators for Simulink and Stateflow Elements.
The gensdd
Function
The gensdd
function, which is included with this example, generates a report that includes these sections:
Title Page
Table of Contents
List of Figures
List of Tables
System Hierarchy
Root System chapter that contains the root block diagram, model notes if any, task and block execution order, and properties of each block in the root diagram
Subsystems chapter that contains the diagram, model notes if any, block execution order, and block properties of the model subsystems
Charts chapter that contains the charts and chart object properties of each of the model charts
Design Data chapter that contains the model variables
System Model Configuration chapter that contains details about the active configuration set for the model
The complete gensdd
function is listed at the end of this example. You can modify the gensdd.m
file
to create a custom system design report.
Generate a PDF System Design Report for the sf_car
Model
Generate a system design report for the sf_car
model and specify that the document is a PDF.
gensdd("sf_car","PDF");
Here is the first page of the report:
This example includes a copy of the report in the file sdd_sf_car_copy.pdf
.
Customize the Report
The gensdd
function uses objects of these Report API classes to find system design elements and report on the system design:
Reporter Classes
Finder and Result Classes
You can use the properties of these objects to filter and format the information that is reported. For example, in the makeSystemHierarchy
function in the gensdd.m
file, you can change the system hierarchy list format to an ordered list by setting the ListFormatter
property of the slreportgen.report.SystemHierarchy
reporter.
function makeSystemHierarchy(rpt, hModel) % Create a chapter reporting on the system hiearchy import mlreportgen.report.* import slreportgen.report.* ch = Chapter("Title", "System Hierarchy"); ol = mlreportgen.dom.OrderedList(); add(ch,SystemHierarchy("Source",hModel,"ListFormatter",ol)); add(rpt, ch); end
The report also uses objects of these Report API classes to create and format the sections of the report:
You can customize the appearance of the report and sections. See Report Formatting Approaches.
The Complete gensdd
Function
type gensdd.m
function gensdd(model,doctype) %GENSDD Generates a system design description from the system"s model % gensdd() generates a PDF system design description for the sf_car % model. % % gensdd(model) generates a PDF system design description for the % specified model. % % gensdd(model, doctype) generates a system design description % document from the specified model and document type: "html", % "docx", or "pdf". % % The generated document is a description of a dynamic system"s design % generated from its Simulink model. The description contains the % following sections: % % * Title Page % * Table of Contents % * List of Figures % * List of Tables % * System Hierarchy % * Root System Chapter -- Contains root block diagram, notes % (if any), task and block execution order, and properties of each % block in the root diagram. % * Subsystems Chapter -- Contains diagram, , notes (if any), block % execution order, and block properties of the subsystems. % * Charts Chapter -- Contains charts and chart object properties of % each of the charts in the model. % * Design Data Chapter -- Contains the model variables. % * System Model Configuration Chapter -- Contains details about the % active configuration set for the model. import mlreportgen.dom.* import mlreportgen.report.* import slreportgen.report.* if nargin < 1 model = "sf_car"; doctype = "pdf"; end if nargin < 2 doctype = "pdf"; end hModel = load_system(model); rpt = slreportgen.report.Report(... "sdd_" + get_param(model, "Name"), doctype); open(rpt); makeTitlePage(rpt, hModel); add(rpt, TableOfContents); add(rpt, ListOfFigures); add(rpt, ListOfTables); makeSystemHierarchy(rpt, hModel); makeRootSystemChapter(rpt, hModel); makeSubsystemsChapter(rpt, hModel); makeChartsChapter(rpt, hModel); makeDesignDataChapter(rpt, hModel); makeModelConfigurationChapter(rpt, hModel); close(rpt); rptview(rpt); close_system(model); end function makeTitlePage(rpt, hModel) import mlreportgen.report.* import slreportgen.report.* tp = TitlePage; tp.Title = upper(get_param(hModel, "Name")); tp.Subtitle = "System Design Description"; tp.Author = "John Doe"; diag = Diagram(hModel); diag.Scaling = "custom"; diag.Height = "2in"; diag.Width = "3in"; tp.Image = getSnapshotImage(diag, rpt); add(rpt, tp); end function makeSystemHierarchy(rpt, hModel) % Create a chapter reporting on the system hierarchy import mlreportgen.report.* import slreportgen.report.* ch = Chapter("Title", "System Hierarchy"); add(ch,SystemHierarchy(hModel)); add(rpt, ch); end function makeRootSystemChapter(rpt, hModel) % Create a chapter reporting on the root system diagram and its blocks % and add the chapter to the main report. import mlreportgen.report.* import slreportgen.report.* import slreportgen.finder.* ch = Chapter("Title", "Root System"); diag = Diagram(hModel); add(ch, diag); add(ch, SystemIO(hModel)); % If model has notes, add Notes section makeNotesSection(ch, hModel); % Add block execution order section makeExecutionOrderSection(ch, hModel); % Add subsections containing the properties for each block in the % subsystem diagram. makeBlockSections(ch, hModel); add(rpt, ch); end function makeSubsystemsChapter(rpt, hModel) % Create a chapter reporting on the subsystems and the blocks that % they contain and add the chapter to the main report. import mlreportgen.report.* import slreportgen.report.* import slreportgen.finder.* % Create a chapter to hold the subsystems. ch = Chapter("Title", "Subsystems"); % Use a finder to find all the subsystem diagrams in the model. The % finder returns an array of SystemDiagramResult objects, each of which % contains a Diagram reporter that creates a snapshot of the subsystem % diagram finder = SystemDiagramFinder(hModel); finder.IncludeRoot = false; systems = find(finder); % Add the subsystem diagram results to the chapter. for system = systems % Create a subsection to contain the subsystem diagram. section = Section("Title", system.Name); % Add the subsystem diagram reporter to the diagram subsection. % Add the subsystem diagram results to the chapter. diag = getReporter(system); diag.MaskedSystemLinkPolicy = "system"; add(section, diag); % If subsystem has notes, add Notes section makeNotesSection(section, system) ioSect = Section("Title", "System Interface"); add(ioSect, SystemIO("Object", system, "ShowDetails", false)); add(section, ioSect); % If the subsystem is nonvirtual, add a subsection detailing the % block execution order if strcmp(system.Type, "Simulink.BlockDiagram") || ... strcmp(get_param(system.Object, ... "IsSubsystemVirtual"), "off") makeExecutionOrderSection(section, system); end % Add subsections containing the properties for each block in the % subsystem diagram. makeBlockSections(section, system); % Add the subsystem diagram section to the chapter. add(ch, section); end % Add the subsystems chapter to the main report. add(rpt, ch); end function makeChartsChapter(rpt, hModel) % Create a chapter reporting on the Stateflow charts and the % objects that they contain and add the chapter to the main report. import mlreportgen.report.* import slreportgen.report.* import slreportgen.finder.* finder = ChartDiagramFinder(hModel); charts = find(finder); if ~isempty(charts) ch = Chapter("Title", "Charts"); for chart = charts section = Section("Title", chart.Name); diag = getReporter(chart); add(section, diag); % Report the objects in this chart objFinder = StateflowDiagramElementFinder(chart); sfObjects = find(objFinder); for sfObj = sfObjects objSection = Section("Title", sfObj.Name); add(objSection, sfObj); add(section, objSection); end add(ch, section); end add(rpt, ch); end end function makeDesignDataChapter(rpt, hModel) % Create a chapter reporting on the model variables import mlreportgen.dom.* import mlreportgen.report.* import slreportgen.report.* import slreportgen.finder.* ch = Chapter("Title", "Design Data"); finder = ModelVariableFinder(hModel); results = find(finder); n = numel(results); if n > 0 s = Section("Title", "Design Data Summary"); vars = cell(n, 4); for i = 1:n result = results(i); % Get link target for variable reporter lt = getVariableID(result); value = getVariableValue(results(i)); vars{i, 1} = InternalLink(lt, results(i).Name); vars{i, 2} = class(value); vars{i, 3} = results(i).Source; vars{i, 4} = results(i).SourceType; end t = FormalTable(["Name", "Type", "Source", "Source Type"], vars); % Set styles for table header t.Header.TableEntriesStyle = {Bold, BackgroundColor("lightgrey")}; % Set styles for entire table t.Width = "100%"; t.Border = "solid"; t.RowSep = "solid"; t.ColSep = "solid"; add(s, t); add(ch, s); s = Section("Title", "Design Data Details"); % Separate multiple variable details be a horizontal rule if n > 1 for result = results(1:end-1) add(s, result); add(s, HorizontalRule); end end add(s, results(end)); add(ch, s); add(rpt, ch); end end function makeModelConfigurationChapter(rpt, hModel) % Create a chapter reporting on the active configuration set of the % reported model. import mlreportgen.report.* import slreportgen.report.* ch = Chapter("Title", "System Model Configuration"); modelConfig = ModelConfiguration(hModel); % Add the reporter to the chapter and chapter to the report add(ch,modelConfig); add(rpt,ch); end function section = makeBlockSections(parent, system) % Create subsections containing the properties of each block in the % system and add it to the parent chapter or subsection. import mlreportgen.report.* import slreportgen.finder.* blocksSection = Section("Title", "Blocks"); finder = BlockFinder(system); elems = find(finder); for elem = elems section = Section("Title", strrep(elem.Name, newline, " ")); add(section, elem); % If this block creates a bus or selects signals from a bus, report % the bus signal details busRptr = slreportgen.report.Bus(elem); add(section, busRptr); add(blocksSection, section); end add(parent, blocksSection); end function makeExecutionOrderSection(parent, system) % Create a section to display a list of blocks in the system in order of % execution. If the system is a top-level model, display information % about all tasks in the model. import mlreportgen.report.* import slreportgen.report.* section = Section("Title", "Block Execution Order"); eo = ExecutionOrder(system); if ~slreportgen.utils.isModel(system) % Only show task details for top-level models eo.ShowTaskDetails = false; end add(section, eo) add(parent, section); end function makeNotesSection(parent, system) % Create a section to display any existing model notes import mlreportgen.report.* import slreportgen.report.* section = Section("Title", "Notes"); notes = Notes(system); if ~isequal(notes.NoteType,"None") add(section,notes); add(parent,section); end end
See Also
slreportgen.report.SystemHierarchy
| slreportgen.report.Diagram
| slreportgen.report.SystemIO
| slreportgen.finder.SystemDiagramFinder
| slreportgen.finder.DiagramResult
| slreportgen.finder.DiagramElementResult
| slreportgen.finder.StateflowDiagramElementFinder
| slreportgen.finder.ModelVariableFinder
| slreportgen.finder.ModelVariableResult
| slreportgen.report.ModelVariable
| slreportgen.finder.BlockFinder
| slreportgen.finder.BlockResult
| slreportgen.finder.ChartDiagramFinder
| slreportgen.report.SimulinkObjectProperties