exponenta event banner

Улучшение читаемости кода для блок-схем

Внешний вид сгенерированного кода для блок-схем

Если имеется Embedded Coder ® и создается код для моделей, включающих объекты Stateflow ®, код из блок-схемы напоминает следующие примеры.

Применяются следующие характеристики:

  • По умолчанию созданный код использует if-elseif-else операторы для представления switch паттерны. Преобразование кода для использования switch-case инструкции см. в разделе Преобразование кода If-Elseif-Else в операторы Switch-Case.

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

  • Комментарии отслеживания для переходов появляются между каждым набором /* и */ маркеры. Дополнительные сведения об отслеживании см. в разделе Элементы Trace Stateflow в сгенерированном коде.

Пример кода для шаблона логики принятия решений

if (modelname_U.In1 == 1.0) {
  /* Transition: '<S1>:11' */
  /* Transition: '<S1>:12' */
  modelname_Y.Out1 = 10.0;

  /* Transition: '<S1>:15' */
  /* Transition: '<S1>:16' */
} else {
  /* Transition: '<S1>:10' */
  if (modelname_U.In1 == 2.0) {
    /* Transition: '<S1>:13' */
    /* Transition: '<S1>:14' */
    modelname_Y.Out1 = 20.0;

    /* Transition: '<S1>:16' */
  } else {
    /* Transition: '<S1>:17' */
    modelname_Y.Out1 = 30.0;
  }
}

Пример кода для шаблона итеративного цикла

for (sf_i = 0; sf_i < 10; sf_i++) {
  /* Transition: '<S1>:40' */
  /* Transition: '<S1>:41' */
  modelname_B.y = modelname_B.y +
    modelname_U.In1;

  /* Transition: '<S1>:39' */
}

Пример кода для шаблона коммутатора

if (modelname_U.In1 == 1.0) {
  /* Transition: '<S1>:149' */
  /* Transition: '<S1>:150' */
  modelname_Y.Out1 = 1.0;

  /* Transition: '<S1>:151' */
  /* Transition: '<S1>:152' */
  /* Transition: '<S1>:158' */
  /* Transition: '<S1>:159' */
} else {
  /* Transition: '<S1>:156' */
  if (modelname_U.In1 == 2.0) {
    /* Transition: '<S1>:153' */
    /* Transition: '<S1>:154' */
    modelname_Y.Out1 = 2.0;

    /* Transition: '<S1>:155' */
    /* Transition: '<S1>:158' */
    /* Transition: '<S1>:159' */
  } else {
    /* Transition: '<S1>:161' */
    modelname_Y.Out1 = 3.0;
  }
}

Новообращенный If-Elseif-Else Код для Switch-Case Заявления

При создании кода для встроенных целей в реальном времени можно выбрать преобразование if-elseif-else код для switch-case заявления. Это преобразование может повысить читаемость кода. Например, когда блок-схема содержит длинный список условий, switch-case структура:

  • Сокращение использования скобок и фигурных скобок

  • Минимизация повторения в созданном коде

Как преобразовать If-Elseif-Else Код для Switch-Case Заявления

ШагЗадачаСсылка
1

Убедитесь, что блок-схема соответствует правилам преобразования.

Проверка содержимого блок-схемы
2

Включите преобразование и создайте код для модели.

Включить преобразование
3

Устранение неполадок созданного кода.

  • Если вы видите switch-case операторы для вашей блок-схемы, вы можете остановить.

  • Если вы видите if-elseif-else , обновите диаграмму и повторите предыдущий шаг.

Устранение неполадок созданного кода

Правила преобразования

Чтобы преобразование произошло, следуйте этим инструкциям. LHS и RHS относятся соответственно к левой и правой сторонам состояния.

КонструкцияПравила, которым необходимо следовать
Блок-схема

Должен иметь значение по умолчанию и два или более уникальных условий.

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

Каждое условие

Должен проверять только равенство.

Необходимо использовать одну и ту же переменную или выражение для LHS. Можно сторнировать LHS и RHS.

Каждый LHS

Должно быть одной переменной или выражением.

Не может быть константой.

Должен иметь целочисленный или перечисляемый тип данных.

Не может иметь никаких побочных эффектов при моделировании.

Например, LHS может считывать, но не записывать глобальные переменные.

Каждый RHS

Должен быть константой или параметром.

Должен иметь целочисленный или перечисляемый тип данных.

Повторяющиеся условия

Если блок-схема имеет повторяющиеся условия, преобразование сохраняет только первое условие. Код отбрасывает другие экземпляры повторяющихся условий.

После удаления дубликатов должны существовать два или более уникальных условия. В противном случае преобразование не выполняется, и код содержит все повторяющиеся условия.

Пример сгенерированного кодаКод после преобразования
if (x == 1) {
    block1
} else if (x == 2) {
    block2
} else if (x == 1) {  // duplicate
    block3
} else if (x == 3) {
    block4
} else if (x == 1) {  // duplicate
    block5
} else {
    block6
}
switch (x) {
    case 1:  
     block1; break;
    case 2:  
     block2; break;
    case 3:  
     block4; break;
    default: 
     block6; break;
}
if (x == 1) {
    block1
} else if (x == 1) {  // duplicate
    block2
} else {
    block3
}

Без изменений, поскольку существует только одно уникальное условие

Пример преобразования кода в Switch-Case Заявления

Предположим, что эта модель содержит одну диаграмму.

Диаграмма содержит блок-схему и четыре функции MATLAB ®.

Функции MATLAB на диаграмме содержат код, указанный в таблице. В каждом случае функция Inline Option имеет значение Auto. Дополнительные сведения о встраивании функций см. в разделе Задание свойств графических функций (поток состояний).

Функция MATLABКодекс
stop
function stop
%#codegen
coder.extrinsic('disp');
disp('Not moving.')

traffic_speed = 0;
slowdown
function slowdown
%#codegen
coder.extrinsic('disp')
disp('Slowing down.')

traffic_speed = 1;
accelerate
function accelerate
%#codegen
coder.extrinsic('disp');
disp('Moving along.')

traffic_speed = 2;
light
function color = light(x)
%#codegen
if (x < 20)
    color = TrafficLights.GREEN;
elseif (x >= 20 && x < 25)
    color = TrafficLights.YELLOW;
else
    color = TrafficLights.RED;
end

Продукция color функции light использует перечисляемый тип TrafficLights. Определение перечисляемого типа в TrafficLights.m является:

classdef TrafficLights < Simulink.IntEnumType
  enumeration
    RED(0)
    YELLOW(5)
    GREEN(10)
  end
end

Дополнительные сведения см. в разделе Определение перечисляемых типов данных (поток состояний).

Проверка содержимого блок-схемы

Проверьте, что блок-схема в диаграмме State flow соответствует правилам в правилах преобразования.

КонструкцияКак конструкция следует правилам
Блок-схема

Существует условие по умолчанию и два уникальных условия:

  • [light(intersection) == RED]

  • [light(intersection) == YELLOW]

Каждое условие

Каждое условие:

  • Проверка равенства

  • Использует тот же вызов функции light(intersection) для LHS

Каждый LHS

Каждый LHS:

  • Содержит одно выражение

  • Является ли вывод вызова функции, а не константой

  • Имеет перечисляемый тип TrafficLights, которые определяются в TrafficLights.m на пути MATLAB. См. раздел Определение перечисляемых типов данных (поток состояний).

  • Использует вызов функции, который не имеет побочных эффектов

Каждый RHS

Каждый RHS:

  • Является перечисляемым значением и, следовательно, константой

  • Имеет перечисляемый тип TrafficLights

Включить преобразование

  1. Откройте диалоговое окно Параметры конфигурации модели (Model Configuration Parameters).

  2. На панели «Создание кода» выберите ert.tlc для системного целевого файла для целевого файла на основе ERT для модели.

  3. На панели Создание кода > Стиль кода установите флажок Преобразовать шаблоны if-elseif-else в операторы switch-case.

    Если этот флажок установлен, преобразование применяется к:

    • Блок-схемы во всех диаграммах модели

    • Функции MATLAB во всех диаграммах модели

    • Все функциональные блоки MATLAB в этой модели

  4. В модели на вкладке Код C (C Code) щелкните Создать (Build), чтобы создать исходный код из модели.

Устранение неполадок созданного кода

Сгенерированный код для блок-схемы выглядит следующим образом:

if (sf_color == RED) {
  /* Transition: '<S1>:11' */
  /* Transition: '<S1>:12' */
  /* MATLAB Function 'stop': '<S1>:23' */
  /* '<S1>:23:6' */
  rtb_traffic_speed = 0;

  /* Transition: '<S1>:15' */
  /* Transition: '<S1>:16' */
} else {
  /* Transition: '<S1>:10' */
  /* MATLAB Function 'light': '<S1>:19' */
  if (ifelse_using_enums_U.In1 < 20.0) {
    /* '<S1>:19:3' */
    /* '<S1>:19:4' */
    sf_color = GREEN;
  } else if ((ifelse_using_enums_U.In1 >= 20.0) && 
             (ifelse_using_enums_U.In1 < 25.0)) {
    /* '<S1>:19:5' */
    /* '<S1>:19:6' */
    sf_color = YELLOW;
  } else {
    /* '<S1>:19:8' */
    sf_color = RED;
  }

  if (sf_color == YELLOW) {
    /* Transition: '<S1>:13' */
    /* Transition: '<S1>:14' */
    /* MATLAB Function 'slowdown': '<S1>:24' */
    /* '<S1>:24:6' */
    rtb_traffic_speed = 1;

    /* Transition: '<S1>:16' */
  } else {
    /* Transition: '<S1>:17' */
    /* MATLAB Function 'accelerate': '<S1>:25' */
    /* '<S1>:25:6' */
    rtb_traffic_speed = 2;
  }
}

Потому что функция MATLAB light появляется встроенным, сравнения неравенства появляются в этих строках кода:

if (ifelse_using_enums_U.In1 < 20.0) {
....
} else if ((ifelse_using_enums_U.In1 >= 20.0) && 
             (ifelse_using_enums_U.In1 < 25.0)) {
....

Потому что неравенство появляется в теле if-elseif-else код для блок-схемы, преобразование в switch-case операторы не встречаются. Выполните одно из следующих действий:

Измените свойство Inlining для функции.  Если изменение блок-схемы не требуется, измените свойство inlining для функции light:

  1. Щелкните правой кнопкой мыши поле функции для light и выберите Свойства.

  2. В диалоговом окне свойств для параметра «Встроенная функция» выберите Function.

  3. Нажмите кнопку ОК, чтобы закрыть диалоговое окно.

Примечание

Изменение свойства inlining для трех других функций MATLAB в диаграмме не требуется. Поскольку блок-схема не вызывает эти функции во время оценки условий, свойство inlining для этих функций может остаться Auto.

При регенерации кода для модели код для блок-схемы теперь выглядит следующим образом:

switch (ifelse_using_enums_light(ifelse_using_enums_U.In1)) {
 case RED:
  /* Transition: '<S1>:11' */
  /* Transition: '<S1>:12' */
  /* MATLAB Function 'stop': '<S1>:23' */
  /* '<S1>:23:6' */
  ifelse_using_enums_Y.Out1 = 0.0;

  /* Transition: '<S1>:15' */
  /* Transition: '<S1>:16' */
  break;

 case YELLOW:
  /* Transition: '<S1>:10' */
  /* Transition: '<S1>:13' */
  /* Transition: '<S1>:14' */
  /* MATLAB Function 'slowdown': '<S1>:24' */
  /* '<S1>:24:6' */
  ifelse_using_enums_Y.Out1 = 1.0;

  /* Transition: '<S1>:16' */
  break;

 default:
  /* Transition: '<S1>:17' */
  /* MATLAB Function 'accelerate': '<S1>:25' */
  /* '<S1>:25:6' */
  ifelse_using_enums_Y.Out1 = 2.0;
  break;
}

Потому что функция MATLAB light больше не отображается встроенным, преобразование в switch-case возникают операторы. Для улучшения читаемости, switch-case заявления предоставляют следующие преимущества:

  • Код сокращает использование скобок и фигурных скобок.

  • Выражение LHS ifelse_using_enums_light(ifelse_using_enums_U.In1) появляется только один раз, сводя к минимуму повторение в коде.

Измените блок-схему, чтобы обеспечить выполнение инструкций Switch-Case.  Если не требуется изменять свойство inlining для функции light, измените схему последовательности операций:

  1. Добавить локальные данные диаграммы color_out с перечисляемым типом TrafficLights.

  2. Заменить каждый экземпляр light(intersection) с color_out.

  3. Добавить действие {color_out = light(intersection)} к переходу блок-схемы по умолчанию.

Теперь диаграмма выглядит аналогично этой диаграмме:

При регенерации кода для модели используется код для схемы последовательности операций. switch-case заявления.

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