Создайте пользовательскую образцовую метрику

Создать вашу собственную образцовую метрику:

  1. Используйте функцию slmetric.metric.createNewMetricClass, чтобы создать новый метрический класс, выведенный из базового класса slmetric.metric.Metric.

  2. Установите следующие свойства класса:

    • ID: Уникальный метрический идентификатор, который получает новые метрические данные.

    • Имя: Имя метрического алгоритма.

    • ComponentScope: Компоненты модели, для которых вычисляется метрика.

    • CompileContext: Скомпилируйте режим для метрического вычисления. Если ваша модель требует, чтобы образцовая метрика потребовала образцовой компиляции, задайте PostCompile. Сбор метрических данных для скомпилированных моделей замедляет производительность.

    • ResultCheckSumCoverage: Задайте, хотите ли вы метрические данные, регенерированные, если исходный файл и Version не изменились.

    • AggregationMode: Как метрический алгоритм агрегировал метрические данные.

    • AggregateComponentDetails: Возвращает все подробные результаты или агрегировал подробные результаты компонента.

    Опционально, установите эти дополнительные свойства:

    • Описание: Описание метрики.

    • Версия: Метрическая версия.

  3. Напишите метрический алгоритм в метод slmetric.metric.Metric, алгоритм. Алгоритм вычисляет метрические данные, заданные классом Advisor.component.Component. Класс Advisor.component.Types задает типы объектов модели, для которых можно вычислить метрические данные.

Создайте образцовую метрику для невиртуального количества блока

Этот пример показывает, как использовать образцовый метрический API, чтобы создать пользовательскую образцовую метрику для подсчета невиртуальных блоков в модели. После создания метрики можно собрать данные для метрики, получить доступ к результатам и экспортировать результаты.

Создайте метрический класс

Используя функцию createNewMetricClass, создайте новый метрический класс named nonvirtualblockcount. Функция создает файл, nonvirtualblockcount.m, в текущей рабочей папке. Файл содержит конструктора и пустой метрический метод алгоритма. В данном примере убедитесь, что вы находитесь в перезаписываемой папке.

className = 'nonvirtualblockcount';
slmetric.metric.createNewMetricClass(className);

Создайте невиртуальную метрику количества блока

Чтобы написать метрический алгоритм, откройте файл nonvirtualblockcount.m и добавьте метрику в файл. Например, чтобы отредактировать файл, используйте команду edit(className). В данном примере можно создать метрический алгоритм путем копирования этой логики в nonvirtualblockcount.m file.

classdef nonvirtualblockcount < slmetric.metric.Metric
    %nonvirtualblockcount calculates number of nonvirtual blocks per level.
    % BusCreator, BusSelector and BusAssign are treated as nonvirtual.
    properties
        VirtualBlockTypes = {'Demux','From','Goto','Ground', ...
            'GotoTagVisiblity','Mux','SignalSpecification', ...
            'Terminator','Inport'};
    end
    
    methods
    function this = nonvirtualblockcount()
        this.ID = 'nonvirtualblockcount';
        this.Name = 'Nonvirtual Block Count';
        this.Version = 1;
        this.CompileContext = 'None';
        this.Description = 'Algorithm that counts nonvirtual blocks per level.';
        this.ComponentScope = [Advisor.component.Types.Model, ...
            Advisor.component.Types.SubSystem];
        this.AggregationMode = slmetric.AggregationMode.Sum;
	    this.AggregateComponentDetails = true;
        this.ResultChecksumCoverage = true;
        this.SupportsResultDetails = true;
            
    end

    function res = algorithm(this, component)
        % create a result object for this component
        res = slmetric.metric.Result();	

        % set the component and metric ID
        res.ComponentID = component.ID;
        res.MetricID = this.ID;
        
        % Practice
        
        D1=slmetric.metric.ResultDetail('identifier 1','Name 1');
        D1.Value=0;
        D1.setGroup('Group1','Group1Name');
        D2=slmetric.metric.ResultDetail('identifier 2','Name 2');
        D2.Value=1;
        D2.setGroup('Group1','Group1Name');
        
        

        % use find_system to get all blocks inside this component
        blocks = find_system(getPath(component), ...
            'SearchDepth', 1, ...
            'Type', 'Block');

        isNonVirtual = true(size(blocks));

        for n=1:length(blocks)
            blockType = get_param(blocks{n}, 'BlockType');

            if any(strcmp(this.VirtualBlockTypes, blockType))
                isNonVirtual(n) = false;
            else
                switch blockType
                    case 'SubSystem'
                        % Virtual unless the block is conditionally executed
                        % or the Treat as atomic unit check box is selected.
                        if strcmp(get_param(blocks{n}, 'IsSubSystemVirtual'), ...
                                'on')
                            isNonVirtual(n) = false;
                        end
                    case 'Outport'
                        % Outport: Virtual when the block resides within
                        % SubSystem block (conditional or not), and 
                        % does not reside in the root (top-level) Simulink window.
                        if component.Type ~= Advisor.component.Types.Model
                            isNonVirtual(n) = false;
                        end
                    case 'Selector'
                        % Virtual only when Number of input dimensions 
                        % specifies 1 and Index Option specifies Select 
                        % all, Index vector (dialog), or Starting index (dialog).
                        nod = get_param(blocks{n}, 'NumberOfDimensions');
                        ios = get_param(blocks{n}, 'IndexOptionArray');

                        ios_settings = {'Assign all', 'Index vector (dialog)', ...
                            'Starting index (dialog)'};

                        if nod == 1 && any(strcmp(ios_settings, ios))
                            isNonVirtual(n) = false;
                        end
                    case 'Trigger'
                        % Virtual when the output port is not present.
                        if strcmp(get_param(blocks{n}, 'ShowOutputPort'), 'off')
                            isNonVirtual(n) = false;
                        end
                    case 'Enable'
                        % Virtual unless connected directly to an Outport block.
                        isNonVirtual(n) = false;

                        if strcmp(get_param(blocks{n}, 'ShowOutputPort'), 'on')
                            pc = get_param(blocks{n}, 'PortConnectivity');

                            if ~isempty(pc.DstBlock) && ...
                                    strcmp(get_param(pc.DstBlock, 'BlockType'), ...
                                    'Outport')
                                isNonVirtual(n) = true;
                            end
                        end
                end
            end
        end

        blocks = blocks(isNonVirtual);

        res.Value = length(blocks);
    end
    end
end
Теперь, когда ваша новая образцовая метрика задана в nonvirtualblockcount.m, укажите новую метрику в метрическом репозитории.
[id_metric,err_msg] = slmetric.metric.registerMetric(className);

Соберите метрические данные

Чтобы собрать метрические данные по моделям, используйте экземпляры slmetric.Engine. Используя метод getMetrics, задайте метрики, которые вы хотите собрать. В данном примере укажите, что невиртуальный блок считает метрику для модели sldemo_mdlref_bus.

Загрузите модель sldemo_mdlref_bus.

model = 'sldemo_mdlref_bus';
load_system(model);

Создайте метрический объект механизма и установите аналитический корень.

metric_engine = slmetric.Engine();
setAnalysisRoot(metric_engine,'Root',model,'RootType','Model');

Соберите метрические данные для невиртуальной метрики количества блока.

execute(metric_engine);
rc = getMetrics(metric_engine,id_metric);

Отобразите и экспортируйте результаты

Чтобы получить доступ к метрикам для вашей модели, используйте экземпляры slmetric.metric.Result. В этом примере отобразите невиртуальные метрики количества блока для sldemo_mdlref_busmodel. Для каждого результата отобразите MetricID, ComponentPath и Value.

for n=1:length(rc)
    if rc(n).Status == 0
        results = rc(n).Results;

        for m=1:length(results)
            disp(['MetricID: ',results(m).MetricID]);
            disp(['  ComponentPath: ', results(m).ComponentPath]);
            disp(['  Value: ', num2str(results(m).Value)]);
            disp(' ');
        end
    else
        disp(['No results for:',rc(n).MetricID]);
    end
    disp(' ');
end

Вот результаты.

MetricID: nonvirtualblockcount
  ComponentPath: sldemo_mdlref_bus
  Value: 15
 
MetricID: nonvirtualblockcount
  ComponentPath: sldemo_mdlref_bus/More Info3
  Value: 0
 
MetricID: nonvirtualblockcount
  ComponentPath: sldemo_mdlref_bus/More Info4
  Value: 0
 
MetricID: nonvirtualblockcount
  ComponentPath: sldemo_mdlref_bus/More Info1
  Value: 0
 
MetricID: nonvirtualblockcount
  ComponentPath: sldemo_mdlref_bus/More Info2
  Value: 0
 
MetricID: nonvirtualblockcount
  ComponentPath: sldemo_mdlref_counter_bus
  Value: 2
 
MetricID: nonvirtualblockcount
  ComponentPath: sldemo_mdlref_counter_bus/COUNTER
  Value: 6
 
MetricID: nonvirtualblockcount
  ComponentPath: sldemo_mdlref_counter_bus/COUNTER/Counter
  Value: 3
 
MetricID: nonvirtualblockcount
  ComponentPath: sldemo_mdlref_counter_bus/COUNTER/Counter/ResetCheck
  Value: 4
 
MetricID: nonvirtualblockcount
  ComponentPath: sldemo_mdlref_counter_bus/COUNTER/Counter/ResetCheck/NoReset
  Value: 2
 
MetricID: nonvirtualblockcount
  ComponentPath: sldemo_mdlref_counter_bus/COUNTER/Counter/ResetCheck/Reset
  Value: 3
 
MetricID: nonvirtualblockcount
  ComponentPath: sldemo_mdlref_counter_bus/COUNTER/Counter/SaturationCheck
  Value: 5
 
MetricID: nonvirtualblockcount
  ComponentPath: sldemo_mdlref_counter_bus/COUNTER/LimitsProcess
  Value: 1
 
MetricID: nonvirtualblockcount
  ComponentPath: sldemo_mdlref_counter_bus/More Info1
  Value: 0
 
MetricID: nonvirtualblockcount
  ComponentPath: sldemo_mdlref_counter_bus/More Info2
  Value: 0

Чтобы экспортировать метрические результаты в XML-файл, используйте метод exportMetrics. Для каждого метрического результата XML-файл включает ComponentID, ComponentPath, MetricID, Value, AggregatedValue и Measure.

filename='MyMetricData.xml';
exportMetrics(metric_engine,filename);

В данном примере не укажите невиртуальную метрику количества блока.

slmetric.metric.unregisterMetric(id_metric);

Закройте модель.

clear;
bdclose('all');

Ограничения

Пользовательские метрические алгоритмы не поддерживают свойство path на объектах компонента:

  • Соединенные диаграммы Stateflow

  • Блоки MATLAB function

Пользовательские метрические алгоритмы не переходят по ссылкам библиотеки.

Смотрите также

| | | | |

Похожие темы