Сконфигурируйте варианты размерности для блоков s-function

Чтобы сконфигурировать символьные размерности для Блоков s-function, можно использовать следующие функции C/C++. Можно сконфигурировать S-функции, чтобы поддержать прямое распространение, обратное распространение или прямое и обратное распространение символьных размерностей в процессе моделирования.

Многие из этих функций возвращают переменную SymbDimsId. SymbDimsId уникальное целочисленное значение. Это значение соответствует каждой символьной спецификации размерности, которую вы создаете, или результат математической операции, которую вы выполняете с символьными размерностями.

S-функции C/C++Цель

ssSetSymbolicDimsSupport

Задайте, поддерживает ли S-функция символьные размерности.

mdlSetInputPortSymbolicDimensions

Задайте символьные размерности входного порта и как те размерности распространяют вперед.

mdlSetOutputPortSymbolicDimensions

Задайте символьные размерности выходного порта и как те размерности распространяют назад.

ssRegisterSymbolicDimsExpr

Создайте SymbDimsId от строки выражения (aExpr). Строка выражения должна сформировать допустимый синтаксис в C.

ssRegisterSymbolicDims

Создайте SymbDimsId от вектора из SymbDimsIds.

ssRegisterSymbolicDimsString

Создайте SymbDimsId от строки идентификатора (aString).

ssRegisterSymbolicDimsIntValue

Создайте SymbDimsId от целочисленного значения (aIntValue)

ssRegisterSymbolicDimsPlus

Создайте SymbDimsId путем добавления двух символьных размерностей.

ssRegisterSymbolicDimsMinus

Создайте SymbDimsId путем вычитания двух символьных размерностей.

ssRegisterSymbolicDimsMultiply

Создайте SymbDimsId путем умножения двух символьных размерностей.

ssRegisterSymbolicDimsDivide

Создайте SymbDimsId путем деления двух символьных размерностей.

ssGetNumSymbolicDims

Получите количество размерностей для SymbDimsId.

ssGetSymbolicDim

Получите SymbDimsId от вектора из SymbDimsIds.

ssSetInputPortSymbolicDimsId

Установите предварительно скомпилированный SymbDimsId из входного порта. Можно вызвать эту функцию из mdlInitializeSizes функция.

ssGetCompInputPortSymbolicDimsId

Получите скомпилированный SymbDimsId из входного порта.

ssSetCompInputPortSymbolicDimsId

Установите скомпилированный SymbDimsId из входного порта.

ssSetOutputPortSymbolicDimsId

Установите предварительно скомпилированный SymbDimsId из выходного порта. Можно вызвать эту функцию из mdlInitializeSizes функция.

ssGetCompOutputPortSymbolicDimsId

Получите скомпилированный SymbDimsId из выходного порта.

ssSetCompOutputPortSymbolicDimsId

Установите скомпилированный SymbDimsId из выходного порта.

ssSetCompDWorkSymbolicDimsId

Установите скомпилированный SymbDimsId из индекса типа данных блока работают (DWork) вектор.

Сгенерируйте код от блока s-function с вариантами размерности

Модель ex_msymbdims_sfcn_one содержит S-функцию, которая вычитает символьную размерность B от символьной входной размерности, A + B. Модель поддерживает прямое распространение, потому что символьные размерности выходных портов установлены. Модель не поддерживает обратное распространение символьных размерностей, потому что скомпилированные символьные размерности входных портов не установлены.

model='ex_msymbdims_sfcn_one';
open_system(model);

sfun_symbdims_sfcn_one.c файл содержит этот код.

type sfun_symbdims_sfcn_one.c
/* Copyright 2014 The MathWorks, Inc. */
#define S_FUNCTION_NAME  sfun_symbdims_sfcn_one
#define S_FUNCTION_LEVEL 2

#include "simstruc.h"

#include <assert.h>

/* Function: mdlInitializeSizes ===============================================
 * Abstract:
 *   Setup sizes of the various vectors.
 */
static void mdlInitializeSizes(SimStruct *S)
{
    ssSetNumSFcnParams(S, 0); /* Number of expected parameters */
    
    ssSetNumContStates(S, 0);
    ssSetNumDiscStates(S, 0);

    if (!ssSetNumInputPorts(S, 1)) return;
    ssSetInputPortDirectFeedThrough(S, 0, 1);
    ssSetInputPortDimensionInfo(S, 0, DYNAMIC_DIMENSION);
    ssSetInputPortRequiredContiguous(S, 0, 1);
    
    if (!ssSetNumOutputPorts(S,1)) return;
    ssSetOutputPortDimensionInfo(S, 0, DYNAMIC_DIMENSION);   
    ssSetNumSampleTimes(S, 1);

    ssSetNumRWork(S, 0);
    ssSetNumIWork(S, 0);
    ssSetNumPWork(S, 0);

    ssSetNumModes(S, 0);
    ssSetNumNonsampledZCs( S, 0);
    
    ssAllowSignalsWithMoreThan2D(S);
    
    ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
    
    ssSetSymbolicDimsSupport(S, true);
}


/*If underspecified for propagation, say i/o are scalars.*/
#if defined(MATLAB_MEX_FILE)
#define MDL_SET_DEFAULT_PORT_DIMENSION_INFO
static void mdlSetDefaultPortDimensionInfo(SimStruct *S)
{
    if( (ssGetOutputPortWidth(S, 0) == DYNAMICALLY_SIZED) 
        && (ssGetInputPortWidth(S, 0) == DYNAMICALLY_SIZED) ) {
        ssSetOutputPortMatrixDimensions(S, 0, 1, 1 );
    }
}
#endif

#if defined(MATLAB_MEX_FILE)
#define MDL_SET_INPUT_PORT_SYMBOLIC_DIMENSIONS
static void mdlSetInputPortSymbolicDimensions(SimStruct* S, 
   int_T portIndex, SymbDimsId symbDimsId)
{
    assert(0 == portIndex);
    // Set the compiled input symbolic dimension.
    ssSetCompInputPortSymbolicDimsId(S,  portIndex, symbDimsId);
    const SymbDimsId symbolId = ssRegisterSymbolicDimsString(S, "B");
    const SymbDimsId outputDimsId = 
       ssRegisterSymbolicDimsMinus(S, symbDimsId, symbolId);
    ssSetCompOutputPortSymbolicDimsId(S, portIndex, outputDimsId);
}
#endif

#if defined(MATLAB_MEX_FILE)
#define MDL_SET_OUTPUT_PORT_SYMBOLIC_DIMENSIONS
static void mdlSetOutputPortSymbolicDimensions(SimStruct *S, 
   int_T portIndex, SymbDimsId symbDimsId)
{
    assert(0 == portIndex);
   // The input dimensions are not set, so this S-function only
	// supports forward propagation.
    ssSetCompOutputPortSymbolicDimsId(S, portIndex, symbDimsId);
}
#endif

/* Function: mdlInitializeSampleTimes =========================================
 * Abstract:
 *    Specify that we inherit our sample time from the driving block.
 *    However, we don't execute in minor steps.
 */
static void mdlInitializeSampleTimes(SimStruct *S)
{
    ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
    ssSetOffsetTime(S, 0, 0.0);
    ssSetModelReferenceSampleTimeDefaultInheritance(S);    
}
/* Function: mdlOutputs =======================================================
 * Abstract:
 *    y=u';
 */
static void mdlOutputs(SimStruct *S, int_T tid)
{
}

/* Function: mdlTerminate =====================================================
 * Abstract:
 *    No termination needed, but we are required to have this routine.
 */
static void mdlTerminate(SimStruct *S)
{
    UNUSED_ARG(S); /* unused input argument */
}



#ifdef  MATLAB_MEX_FILE    /* Is this file being compiled as a MEX-file? */
#include "simulink.c"      /* MEX-file interface mechanism */
#else
#include "cg_sfun.h"       /* Code generation registration function */
#endif

Simulink.Parameter object s A и B содержит эти определения.

type definitions.txt
A = Simulink.Parameter;
A.DataType = 'int32';
A.Value = 6;
A.Min=5;
A.Max=7;
A.CoderInfo.StorageClass = 'Custom';
A.CoderInfo.CustomStorageClass = 'ImportedDefine';
A.CoderInfo.CustomAttributes.HeaderFile = 'ImportedDefinitions.h';

B = Simulink.Parameter;
B.DataType = 'int32';
B.Value = 10;
B.Min=9;
B.Max=11;
B.CoderInfo.StorageClass = 'Custom';
B.CoderInfo.CustomStorageClass = 'ImportedDefine';
B.CoderInfo.CustomAttributes.HeaderFile = 'ImportedDefinitions.h';

ImportedDefinitions заголовочный файл содержит этот код.

type ImportedDefinitions.h
/* Copyright 2014 The MathWorks, Inc. */
#ifndef _IMPORTEDDEFINITIONS_H_
#define _IMPORTEDDEFINITIONS_H_
#define A 6
#define B 10
#endif

В диалоговом окне Configuration Paramters панель Пользовательского кода содержит #include "ImportedDefinitions.h" оператор.

sfun_symbdims_sfcn_one S-функция встраивается, таким образом, файл TLC с этим кодом должен присутствовать на пути с моделью и другими вспомогательными файлами.

type sfun_symbdims_sfcn_one.tlc
%implements "sfun_symbdims_sfcn_one" "C"


%function BlockInstanceSetup(block, system) void
%endfunction

%% Function: BlockOutputSignal =================================================
%function BlockOutputSignal(block,system,portIdx,ucv,lcv,idx,retType) void
%endfunction

%% Function: Outputs ===========================================================
%%
%function Outputs(block, system) Output


  %assign rollVars = ["U", "Y"]
  %roll idx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars
    %%
    %assign u  = LibBlockInputSignal( 0, "", lcv, idx)
    %assign y  = LibBlockOutputSignal(0, "", lcv, idx)
                                                           
    %<y> = %<u>;
                                                      
  %endroll

%endfunction %% Outputs



Чтобы сгенерировать MEX-функцию, в командной строке, вводят эту команду:

mex sfun_symbdims_sfcn_one.c
Building with 'gcc'.
MEX completed successfully.

Сгенерируйте код для модели.

currentDir=pwd;
slbuild(model);
### Starting build procedure for: ex_msymbdims_sfcn_one
### Successful completion of build procedure for: ex_msymbdims_sfcn_one

Build Summary

Top model targets built:

Model                  Action                       Rebuild Reason                                    
======================================================================================================
ex_msymbdims_sfcn_one  Code generated and compiled  Code generation information file does not exist.  

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 6.9991s

Просмотрите сгенерированный код для модели. ex_msymbdims_sfcn_one_step функция содержит этот код. Код S-функции установлен встроенный и символьные размерности A, и B находятся в сгенерированном коде.

cfile=fullfile(currentDir, 'ex_msymbdims_sfcn_one_ert_rtw','ex_msymbdims_sfcn_one.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);
/* Model step function */
void ex_msymbdims_sfcn_one_step(void)
{
  int32_T i;

  /* Gain: '<Root>/Gain' incorporates:
   *  Concatenate: '<Root>/Matrix Concatenate'
   *  Inport: '<Root>/In1'
   */
  for (i = 0; i < A; i++) {
    ex_msymbdims_sfcn_one_B.MatrixConcatenate[i] = 2.0 *
      ex_msymbdims_sfcn_one_U.In1[i];
  }

  /* End of Gain: '<Root>/Gain' */

  /* Gain: '<Root>/Gain2' incorporates:
   *  Concatenate: '<Root>/Matrix Concatenate'
   *  Inport: '<Root>/In2'
   */
  for (i = 0; i < B; i++) {
    ex_msymbdims_sfcn_one_B.MatrixConcatenate[A + i] = 2.0 *
      ex_msymbdims_sfcn_one_U.In2[i];
  }

  /* End of Gain: '<Root>/Gain2' */

  /* S-Function (sfun_symbdims_sfcn_one): '<Root>/Minus' incorporates:
   *  Outport: '<Root>/Out1'
   */
  {
    int_T i1;
    const real_T *u0 = &ex_msymbdims_sfcn_one_B.MatrixConcatenate[0];
    real_T *y0 = &ex_msymbdims_sfcn_one_Y.Out1[0];
    for (i1=0; i1 < ((A + B)); i1++) {
      y0[i1] = u0[i1];
    }
  }
}

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

bdclose(model);

S-функция, которая поддерживает прямое и обратное распространение символьных размерностей

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

static void mdlInitializeSizes(SimStruct *S)
{
     // Enable symbolic dimensions for the s-function.
     ssSetSymbolicDimsSupport(S, true);
}

#if defined(MATLAB_MEX_FILE)
#define MDL_SET_INPUT_PORT_SYMBOLIC_DIMENSIONS
static void mdlSetInputPortSymbolicDimensions(SimStruct* S, 
   int_T portIndex, SymbDimsId symbDimsId)
{
    assert(0 == portIndex);
    
    ssSetCompInputPortSymbolicDimsId(S,  portIndex, symbDimsId);
    
    assert(2U == ssGetNumSymbolicDims(S, symbDimsId));
    
    if (SL_INHERIT == 
        ssGetCompOutputPortSymbolicDimsId(S, portIndex)) {

        const SymbDimsId idVec[] = {
            ssGetSymbolicDim(S, symbDimsId, 1),
            ssGetSymbolicDim(S, symbDimsId, 0)};
        // Register the transposed dimensions.
       // Set the output symbolic dimension to the resulting id.
  const SymbDimsId outputDimsId = 
            ssRegisterSymbolicDims(S, idVec, 2U);

        ssSetCompOutputPortSymbolicDimsId(S, portIndex, 
           outputDimsId);
    }
}
#endif

#if defined(MATLAB_MEX_FILE)
#define MDL_SET_OUTPUT_PORT_SYMBOLIC_DIMENSIONS
static void mdlSetOutputPortSymbolicDimensions(SimStruct *S, 
    int_T portIndex, SymbDimsId symbDimsId)
{
    assert(0 == portIndex);
    ssSetCompOutputPortSymbolicDimsId(S, portIndex, symbDimsId);

    assert(2U == ssGetNumSymbolicDims(S, symbDimsId));
    
    if (SL_INHERIT == 
        ssGetCompInputPortSymbolicDimsId(S, portIndex)) {

        const SymbDimsId idVec[] = {
            ssGetSymbolicDim(S, symbDimsId, 1),
            ssGetSymbolicDim(S, symbDimsId, 0)};
        const SymbDimsId inputDimsId = 
            ssRegisterSymbolicDims(S, idVec, 2U);
        // Register the transposed dimensions.
       // Set the input symbolic dimension to the resulting id.
        ssSetCompInputPortSymbolicDimsId(S, portIndex, inputDimsId);
    }
}
#endif

Похожие темы

Для просмотра документации необходимо авторизоваться на сайте