exponenta event banner

Проверка S-функций с помощью API анализатора S-функций

Использование API анализатора S-функций для выполнения проверок качества C-MEX S-функции в модели или библиотеке. Эти проверки выявляют потенциальные проблемы и улучшения и предлагают решения. В этом учебном пособии показано, как:

  • Поиск S-функций в модели

  • Укажите сведения о построении для S-функций

  • Укажите параметры и запустите анализатор S-функции

  • Просмотр и интерпретация результатов

Предпосылки

Для завершения обучения необходимы следующие продукты:

  • MATLAB ®

  • Симулинк ®

  • Polyspace ® (опционально)

  • Компилятор C - для большинства платформ компилятор C по умолчанию поставляется с установкой MATLAB. Список поддерживаемых компиляторов см. в разделе Изменение компилятора по умолчанию. Также можно изменить компилятор по умолчанию с помощью mex -setup команда.

Настройка рабочей среды

  1. Создание локальной рабочей папки, например C:\sfa.

  2. Изменение на docroot\toolbox\simulink\examples папка. В командной строке MATLAB введите:

    cd(fullfile(docroot, 'toolbox', 'simulink', 'examples'))

  3. Скопируйте перечисленные файлы в локальную рабочую папку:

    • ex_slexSfunctionCheckExample.slx

    • external.c

    • external.h

    • sfcnModifyMinorStepDiscState.c

    • sfcnModifyMinorStepDiscState_wrapper.c

    • sfcnUpdateModifyContinuous.c

    • sfcnUpdateModifyContinuous_wrapper.c

    • sfcnUseExternalSrc.c

    • slexBadSFcn.c

    • slexBadSFcn_wrapper.c

Выполнение S-функциональных проверок

Откройте новый сценарий из редактора MATLAB и сохраните его как ex_slexSfunctionCheckScript.m. Чтобы просмотреть пример модели, дважды щелкните ex_slexSfunctionCheckExample.slx в текущей папке или типе ex_slexSfunctionCheckExample в командной строке MATLAB.

Укажите модель

model = 'ex_slexSfunctionCheckExample'

Найти S-функции в модели (необязательно)

Использовать Simulink.sfunction.analyzer.findSfunctions для просмотра всех S-функций, подлежащих анализу в модели. Этот метод не находит S-функции в ссылочной модели.

sfunctions = Simulink.sfunction.analyzer.findSfunctions(model)

Указать сведения о построении (необязательно)

Для указания сведений о построении, таких как исходный код S-функции, внешние библиотеки и заголовочные файлы, можно использовать Simulink.sfunction.analyzer.BuildInfo. В этом учебном пособии, поскольку в модели имеется четыре S-функции, существует четыре различных BuildInfo объекты. Дополнительные сведения см. в разделе Simulink.sfunction.Analyzer и Simulink.sfunction.analyzer.BuildInfo.

bdInfo1= Simulink.sfunction.analyzer.BuildInfo('sfcnUseExternalSrc.c',...
                                              'ExtraSrcFileList',{'external.c'},...
                                              'SrcPaths',{pwd},'IncPaths',{pwd});
bdInfo2= Simulink.sfunction.analyzer.BuildInfo('sfcnModifyMinorStepDiscState.c',...
                                              'ExtraSrcFileList',{'sfcnModifyMinorStepDiscState_wrapper.c'},...
                                              'SrcPaths',{pwd});   
bdInfo3= Simulink.sfunction.analyzer.BuildInfo('sfcnUpdateModifyContinuous.c',...
                                              'ExtraSrcFileList',{'sfcnUpdateModifyContinuous_wrapper.c'},...
                                              'SrcPaths',{pwd});
bdInfo4= Simulink.sfunction.analyzer.BuildInfo('slexBadSFcn.c',...
                                              'ExtraSrcFileList',{'slexBadSFcn_wrapper.c'},...
                                              'SrcPaths',{pwd});       

Задать параметры (необязательно)

Можно настроить параметры для выполнения анализатора S-функций с помощью Simulink.sfunction.analyzer.Options класс. Можно включить проверку Polyspace Code Prover™ и проверку надежности параметров, задать максимальное время моделирования модели и задать путь отчета. Если класс не используется для задания какой-либо из опций, к анализу применяются опции по умолчанию. Посмотрите Simulink.sfunction.analyzer.Options для получения дополнительной информации.

Примечание

Выполнение проверки надежности кода Polyspace Code Prover и параметров занимает некоторое время.

Для выполнения проверок средства проверки кода Polyspace требуется лицензия Polyspace. Дополнительные сведения об использовании проверок Polyspace в анализаторе S-функций см. в разделе Включение проверок Polyspace. В данном учебном пособии включаются проверки надежности параметров.

opts = Simulink.sfunction.analyzer.Options();
opts.EnableRobustness = 1;

Выполнение проверок и просмотр результатов

Запустите проверку анализатора S-функций с помощью Simulink.sfunction.Analyzer.run. Затем используйте Simulink.sfunction.Analyzer.generateReport для просмотра проблем в модели или коде.

sfunAnalyzer = Simulink.sfunction.Analyzer(model,'BuildInfo',{bdInfo1,bdInfo2,bdInfo3,bdInfo4},'Options',opts);  
analysisResult=sfunAnalyzer.run();
sfunAnalyzer.generateReport()
При применении, generateReport способ создает struct и HTML-отчет о результатах S-функциональных проверок анализатора.

analysisResult = 

  struct with fields:

       TimeGenerated: '13-Jul-2017 13:22:37'
            Platform: 'win64'
             Release: '(R2017b)'
     SimulinkVersion: '9.0'
      ExemptedBlocks: {}
    MexConfiguration: [1×1 mex.CompilerConfiguration]
                Data: [4×4 struct]

Изучение и устранение проблем

Пример модели имеет два предупреждения в Source Code Checks и четыре вопроса, касающиеся S-function MEX-file checks. В целом, предупреждения не так значимы, как неудачи, но они являются хорошими источниками для получения дополнительной информации о ваших S-функциях.

  1. Эта проблема имеет код описания MinorStepModifyDiscreteStates. Это описание ошибки указывает, что дискретные состояния блока изменяются на незначительном шаге в mdlOutputs. Чтобы устранить эту проблему, дискретные состояния должны быть изменены только на основном шаге, охраняемом ssIsMajorTimeStep.

    Исходный кодИзмененный код
    MinorStepDiscState_Outputs_wrapper(u0, y0, xC);
        if (ssGetT(S)>0.5) {
            xD[0] = xD[0]+1;
            xD[1] = xD[0]+xD[1]*2.0;
        }
        if (ssGetT(S)>0.5) {
           if (ssIsMajorTimeStep(S)) { 
            xD[0] = xD[0]+1;
            xD[1] = xD[0]+xD[1]*2.0;
           } 
        }

  2. MEX Compile Check код описания указывает на наличие неиспользуемой переменной в строке, указанной в отчете. Это предупреждение устраняется путем удаления строки 208 и повторного выполнения кода.

    Исходный кодИзмененный код
    static void mdlOutputs(SimStruct *S, int_T tid)
    {
        const real_T *u0 = (const real_T*) ssGetInputPortSignal(S,0);
        real_T        *y0  = (real_T *)ssGetOutputPortRealSignal(S,0);
        real_T   *xC = ssGetContStates(S);
    
        *y0 = *xC;
    }
    static void mdlOutputs(SimStruct *S, int_T tid)
    {
        // const real_T *u0 = (const real_T*) ssGetInputPortSignal(S,0);
        real_T        *y0  = (real_T *)ssGetOutputPortRealSignal(S,0);
        real_T   *xC = ssGetContStates(S);
    
        *y0 = *xC;
    }

  3. Код описания MdlUpdateModifyContinuousStates указывает, что в исходном коде S-функции (в данном случае в исходном коде блока S-Function1), непрерывные состояния изменяются в его mdlUpdate способ. Изменить состояния блока можно только на основном шаге времени с помощью ssSetSolverNeedsReset макро.

    Исходный кодИзмененный код
    #define MDL_UPDATE
    static void mdlUpdate(SimStruct *S, int_T tid)
    {
        real_T   *xC = ssGetContStates(S);
                *xC = *xC + 1.0;
    }
    #define MDL_UPDATE
    static void mdlUpdate(SimStruct *S, int_T tid)
    {
        real_T   *xC = ssGetContStates(S);
        // Modify continuous states
        if (ssIsMajorTimeStep(S)) {
                *xC = *xC + 1.0;
            ssSetSolverNeedsReset(S);
        }
    }

  4. Код описания MEX Compile Check указывает, что переменные outputDimsInfo и inputDimsInfo не используются в исходном коде. Это можно исправить, прокомментировав или удалив строки, содержащие эти переменные.

    Исходный кодИзмененный код
    static void mdlInitializeSizes(SimStruct *S)
    {
        DECL_AND_INIT_DIMSINFO(inputDimsInfo);
        DECL_AND_INIT_DIMSINFO(outputDimsInfo);
        ssSetNumSFcnParams(S, NPARAMS);
    static void mdlInitializeSizes(SimStruct *S)
    {
        // DECL_AND_INIT_DIMSINFO(inputDimsInfo);
        // DECL_AND_INIT_DIMSINFO(outputDimsInfo);
        ssSetNumSFcnParams(S, NPARAMS);

  5. Код описания CombinedMdlOutputsMdlUpdateWithDiscreteState указывает, что S-функция имеет дискретные состояния, и вам необходимо использовать MdlUpdate и MdlOutputs методы в коде отдельно. В качестве решения для этого кода описания определите отдельный mdlUpdate для изменения состояний в S-функции.

    #define MDL_UPDATE
    static void mdlUpdate(SimStruct *S, int_T tid)
    {
        /* update the discrete states here! */
        real_T   *xD = ssGetDiscStates(S);
    }

  6. Код описания DeclareCanBeConditionalExecWithState указывает, что у вас есть данные, похожие на данные о состоянии, или если вы используете несколько образцов в модели, вы не можете использовать SS_OPTION_CAN_BE_CALLED_CONDITIONALLY в исходном коде S-функции.

    Чтобы устранить проблему в данном примере, удалите ssSetOptions функция.

    Исходный кодИзмененный код
    static void mdlInitializeSizes(SimStruct *S)
    {
        DECL_AND_INIT_DIMSINFO(inputDimsInfo);
        DECL_AND_INIT_DIMSINFO(outputDimsInfo);
        ssSetNumSFcnParams(S, NPARAMS);
         if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
    	 return; /* Parameter mismatch will be reported by Simulink */
         }
    
        ssSetNumContStates(S, NUM_CONT_STATES);
        ssSetNumDiscStates(S, NUM_DISC_STATES);
    
    
        if (!ssSetNumInputPorts(S, NUM_INPUTS)) return;
        ssSetInputPortWidth(S, 0, INPUT_0_WIDTH);
        ssSetInputPortDataType(S, 0, SS_DOUBLE);
        ssSetInputPortComplexSignal(S, 0, INPUT_0_COMPLEX);
        ssSetInputPortDirectFeedThrough(S, 0, INPUT_0_FEEDTHROUGH);
        ssSetInputPortRequiredContiguous(S, 0, 1); /*direct input signal access*/
    
        if (!ssSetNumOutputPorts(S, NUM_OUTPUTS)) return;
        ssSetOutputPortWidth(S, 0, OUTPUT_0_WIDTH);
        ssSetOutputPortDataType(S, 0, SS_DOUBLE);
        ssSetOutputPortComplexSignal(S, 0, OUTPUT_0_COMPLEX);
        ssSetNumSampleTimes(S, 1);
        ssSetNumRWork(S, 0);
        ssSetNumIWork(S, 0);
        ssSetNumPWork(S, 0);
        ssSetNumModes(S, 0);
        ssSetNumNonsampledZCs(S, 0);
    
    
        ssSetOptions(S, SS_OPTION_CAN_BE_CALLED_CONDITIONALLY);
    }
    static void mdlInitializeSizes(SimStruct *S)
    {
        DECL_AND_INIT_DIMSINFO(inputDimsInfo);
        DECL_AND_INIT_DIMSINFO(outputDimsInfo);
        ssSetNumSFcnParams(S, NPARAMS);
         if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
    	 return; /* Parameter mismatch will be reported by Simulink */
         }
    
        ssSetNumContStates(S, NUM_CONT_STATES);
        ssSetNumDiscStates(S, NUM_DISC_STATES);
    
    
        if (!ssSetNumInputPorts(S, NUM_INPUTS)) return;
        ssSetInputPortWidth(S, 0, INPUT_0_WIDTH);
        ssSetInputPortDataType(S, 0, SS_DOUBLE);
        ssSetInputPortComplexSignal(S, 0, INPUT_0_COMPLEX);
        ssSetInputPortDirectFeedThrough(S, 0, INPUT_0_FEEDTHROUGH);
        ssSetInputPortRequiredContiguous(S, 0, 1); /*direct input signal access*/
    
        if (!ssSetNumOutputPorts(S, NUM_OUTPUTS)) return;
        ssSetOutputPortWidth(S, 0, OUTPUT_0_WIDTH);
        ssSetOutputPortDataType(S, 0, SS_DOUBLE);
        ssSetOutputPortComplexSignal(S, 0, OUTPUT_0_COMPLEX);
        ssSetNumSampleTimes(S, 1);
        ssSetNumRWork(S, 0);
        ssSetNumIWork(S, 0);
        ssSetNumPWork(S, 0);
        ssSetNumModes(S, 0);
        ssSetNumNonsampledZCs(S, 0);
    
    }

При устранении всех проблем в модели в отчете отображаются зеленые флажки для каждой группы проверок.

Включить проверки API без документов

Во избежание несовместимости в будущих версиях можно проверить использование недокументированных API в исходном коде S-функции. Чтобы включить эту проверку, в объекте Simulink.sfunction.analyzer.Options задайте EnableUsePublishedOnly на 1. Кроме того, при создании файлов MEX используйте -DUSE_PUBLISHED_ONLY вариант. Например, попробуйте построить sfcnModifyMinorStepDiscState.c с этой опцией, используя:

mex sfcnModifyMinorStepDiscState.c -DUSE_PUBLISHED_ONLY

Включить проверки полиспейса

S-function analyzer позволяет выполнять проверку кода в программе Polyspace Code Prover. Чтобы включить проверку, в объекте Simulink.sfunction.analyzer.Options задайте EnablePolyspace на 1. Программа Polyspace Code Prover делит чеки на красные, зеленые, оранжевые и серые. Дополнительные сведения о типах проверок см. в разделах Результат проверки кода и Цвета исходного кода (Проверка кода в пространстве).

В анализаторе S-функций наиболее важным кодом ошибки является красный. Если исходный код S-функции не выполняется по всем путям, средство проверки кода Polyspace выдает красную проверочную ошибку. Дополнительные сведения см. в разделе Интерпретация результатов проверки кода в интерфейсе пользователя Polyspace Desktop (проверка кода Polyspace). Ниже приведен пример устранения ошибки проверки красного цвета.

Красная проверка проверки кода Polyspace указывает на наличие проблемы в исходном коде S-функции. Чтобы исследовать проблему с помощью Polyspace, щелкните гиперссылку в отчете. Эта ссылка автоматически открывает окно проекта Polyspace. На панели «Список результатов» разверните «Красная проверка» и выберите ошибку. Исходный файл откроется в окне Источник (Source). В этом окне можно исправить и сохранить код так же, как в редакторе MATLAB.

Код ошибки средства проверки кода Polyspace указывает на проблему с указателем. Указатель *p выходит за границы, поскольку используется в более раннем цикле. Исправьте ошибку, заменив этот указатель выбранной переменной или удалив *p из этой строки кода.

Исходный кодИзмененный код
    if (return_val < 3)
    {
        tmp = *p+5; /* Out of bounds */
        tmp++;
        return_val = 10;
    }
    if (return_val < 3)
    {
        tmp = 5; 
        tmp++;
        return_val = 10;
    }

См. также

| | |

Связанные темы

Связанные темы