Хранение данных в сгенерированном коде

Сведения о хранилищах данных

Хранилище данных содержит данные, которые доступны в иерархии модели на уровне, на котором определено хранилище данных, или ниже него. Хранилища данных могут позволить подсистемам и ссылочным моделям обмениваться данными без необходимости использования портов ввода-вывода для передачи данных от уровня к уровню. Смотрите Хранилища Данных с Блоками Памяти Хранилища Данных для получения информации о Хранилищах данных в Simulink®. В этом разделе приведены дополнительные сведения о генерации кода хранилища данных.

Сгенерируйте код для блоков памяти хранилища данных

Чтобы управлять кодом, сгенерированным для блока Data Store Memory, примените класс памяти к хранилищу данных. Можно связать Data Store Memory блок с сигнальным объектом, который вы храните в рабочей области или словаре данных, и кода системы управления генерацию для блока путем применения класса памяти к объекту:

  1. На вкладке Modeling нажмите Model Data Editor.

  2. В Model Data Editor выберите вкладку Data Stores.

  3. Начните редактировать имя целевого Data Store Memory блока, щелкнув соответствующую строку в Name столбце.

  4. Рядом с именем нажмите кнопку и выберите Create and Resolve.

  5. В диалоговом окне «Создание новых данных» установите Value равным Simulink.Signal. Вы можете использовать выпадающий список Location, чтобы выбрать рабочую область для хранения полученных Simulink.Signal объект.

  6. Нажмите Create. The Simulink.Signal объект, имя которого совпадает с именем хранилища данных, появляется в целевой рабочей области. Simulink выбирает параметры блоков Data store name must resolve to Simulink signal object.

    Когда откроется диалоговое окно свойств для объекта, нажмите OK.

  7. В приложении Simulink Coder или Embedded Coder откройте редактор Отображения. На вкладке C Code выберите Code Interface > Individual Element Code Mappings.

  8. На вкладке Data Stores примените целевой класс памяти.

Примечание

Когда блок Data Store Memory связан с объектом сигнала, отображение между Data store name и именем объекта сигнала должно быть один на один. Если две или более идентично названных сущностей сопоставлены с одним и тем же объектом сигнала, конфликт по совпадению имен помечается как ошибка во времени генерации кода. Для получения дополнительной информации см. раздел «Разрешение конфликтов в строении объектов сигнала для генерации кода».

Классы памяти для блоков памяти хранилища данных

Можно управлять тем, как блоки Data Store Memory в модели хранятся и представлены в сгенерированном коде, путем присвоения классов памяти и определителей типов. Вы делаете это почти точно так же, как вы присваиваете классы памяти и типы для состояний блока.

Data Store Memory блоки, как состояния блока, имеют Auto класс памяти по умолчанию, и их память хранится в DWork вектор. Символическое имя места хранения определяется именем хранилища данных.

Можно сгенерировать код из нескольких блоков Data Store Memory, которые имеют одно и то же имя хранилища данных, с учетом следующего ограничения: максимум один из одинаково названных блоков может иметь класс памяти, отличный от Auto. Если это условие не выполнено, выдается сообщение об ошибке.

Для блоков с Auto класс памяти, генератор кода создает уникальное символьное имя для каждого блока, чтобы избежать конфликтов имен. Для блоков памяти хранилища данных с классами памяти, отличными от Autoсгенерированный код использует имя хранилища данных в качестве символа.

В следующей модели блок Data Store Write записывает в память, объявленную блоком Data Store Memory myData:

Чтобы управлять объявлением хранилища для блока Data Store Memory, в приложении кодера используйте редактор Отображения. На вкладке Data Stores выберите Storage Class для блока.

Data Store Memory блоки невиртуальны, потому что код генерируется для их инициализации в .c и .cpp файлы и их объявления в заголовочных файлах. В следующей таблице показано, как код, сгенерированный для блока Data Store Memory в предыдущей модели, отличается для различных классов памяти. В таблице приведены переменные объявления и MdlOutputs код сгенерирован для myData блок.

Класс памяти

Декларация

Код

Auto или Model default (когда Code Mapping Editor задает Default класс памяти)

В model.h

typedef struct 
D_Work_tag 
{
  real_T myData;
} 
D_Work;

В model.c или model.cpp

/* Block states (auto storage) */
D_Work model_DWork;
model_DWork.myData = 
  rtb_SineWave;

ExportedGlobal

В model.c или model.cpp

/* Exported block states */
real_T myData; 

В model.h

extern real_T myData;
myData = rtb_SineWave;

ImportedExtern

В model_private.h

extern real_T myData;
myData = rtb_SineWave;

ImportedExternPointer

В model_private.h

extern real_T *myData;
(*myData) = rtb_SineWave;

Для получения информации о применении классов памяти смотрите Строение Генерации кода C для Элементов Интерфейса Модели.

Для моделей ERT можно сохранить размерности многомерных массивов в хранилищах данных. Для получения дополнительной информации смотрите Сохранить размерности многомерных массивов в Сгенерированном коде (Embedded Coder).

Буферизация хранилища данных в сгенерированном коде

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

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

Применяется следующий порядок выполнения:

  1. Блок Data Store Read буферизует текущее значение хранилища данных A на его выходе.

  2. Блок Abs1 использует буферизованный выход Data Store Read.

  3. Блок Data Store Write обновляет хранилище данных.

  4. Блок Abs использует буферизованный выход Data Store Read.

Поскольку выход Data Store Read является буфером, Abs и Abs1 используют одно и то же значение: значение хранилища данных во время чтения хранилища данных.

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

В этом примере применяется следующий порядок выполнения:

  1. Блок Data Store Read буферизует текущее значение хранилища данных A на его выходе.

  2. Выполняется атомарная подсистема.

  3. Блок Sum добавляет вывод Атомарная подсистема к выходу Data Store Read.

Simulink принимает, что Атомарная Подсистема может обновить хранилище данных, поэтому Simulink буферизует хранилище данных. Атомарная подсистема выполняет после того, как Data Store Read буферизует свой выход, и буфер предоставляет способ для блока Sum использовать значение хранилища данных, как это было при выполнении Data Store Read.

В некоторых случаях генератор кода определяет, что он может оптимизировать выходной буфер для блока Data Store Read, и сгенерированный код относится к хранилищу данных непосредственно, а не к буферизированному значению его. Следующий рисунок показывает пример:

В сгенерированном коде аргумент fabs() функция является хранилищем данных A вместо буферизованного значения.

Хранилища данных, общие для образцов переиспользуемой модели

Можно использовать хранилище данных для совместного использования части данных между образцами переиспользуемой модели-ссылки (см. Раздел «Обмен данными среди образцов модели-ссылки») или модели, которую вы конфигурируете, чтобы сгенерировать повторно входящий код (путем установки параметра конфигурации Code interface packaging равным Reusable function). Если вы реализуете хранилище данных как блок Data Store Memory и выберете параметр Share across model instances:

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

  • Если у вас есть Embedded Coder®, чтобы ограничить доступ таким образом, чтобы только код, сгенерированный из модели, мог использовать хранилище данных, сконфигурируйте хранилище данных как static путем применения класса памяти FileScope. Для получения дополнительной информации о FileScope и другие классы памяти, см. Выбор класса памяти для управления представлением данных в сгенерированном коде (Embedded Coder).

Структуры в сгенерированном коде с использованием хранилищ данных

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

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

Исследуйте модель примера

  1. Откройте пример модели ex_bus_struct_in_code.

    Модель содержит три подсистемы, которые выполняют вычисления на входах с верхнего уровня модели. В каждой подсистеме блок Data Store Memory сохраняет промежуточный вычисленный сигнал.

  2. Сгенерируйте код с моделью. В отчете о генерации кода просмотрите файл ex_bus_struct_in_code.c. Код определяет глобальную переменную для каждого хранилища данных.

    real_T BioBTURate;
    real_T CoalBTURate;
    real_T GasBTURate;

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

Сконфигурируйте хранилище данных

Сконфигурируйте хранилище данных так, чтобы оно содержало несколько сигналов путем создания типа шины, который будет использоваться в качестве типа данных хранилища данных. Определите тип шины, используя ту же иерархию элементов, что и структура, которая должна отображаться в сгенерированном коде.

  1. Откройте инструмент «Редактор шин».

    buseditor
  2. Определите новый тип шины Raw_BTU_Rate с одним элементом для каждого из трех целевых сигналов. Назовите элементы BioBTU, GasBTU, и CoalBTU.

  3. На верхнем уровне модели примера добавьте блок Data Store Memory.

  4. На вкладке Modeling нажмите Model Data Editor.

  5. В Model Data Editor смотрите вкладку Data Stores.

  6. Для нового блока Data Store Memory используйте столбец Name, чтобы задать имя хранилища данных Raw_BTU_Data.

  7. Используйте столбец Data Type, чтобы задать тип данных хранилища данных Bus: Raw_BTU_Rate.

  8. В редакторе Отображения на вкладке Data Stores примените класс памяти ExportedGlobal на Raw_BTU_Data.

Запись в элементы хранилища данных

Чтобы записать в определенный элемент массива хранилища данных, используйте блок Data Store Write. На вкладке Element Assignment в диалоговом окне можно задать запись в один элемент, набор элементов или все содержимое хранилища данных.

  1. Откройте Biomass Calc подсистему.

  2. Удалите Data Store Memory блок BioBTURate.

  3. В диалоговом окне блока Data Store Write установите Data store name равным Raw_BTU_Data.

  4. На вкладке Element Assignment, в разделе Signals in the bus, разверните содержимое хранилища данных Raw_BTU_Data. Щелкните элемент BioBTU, а затем нажмите Select. Нажмите OK.

  5. Аналогичным образом измените Gas Calc и Coal Calc подсистемы.

    • Удалите Data Store Memory блок в каждой подсистеме.

    • В каждом < reservedrangesplaceholder2 > диалоговом окне блока установите Data store name равным Raw_BTU_Data.

    • В подсистеме Gas Calc используйте блок Data Store Write для записи в элемент хранилища данных GasBTU. В подсистеме Coal Calc запишите в элемент CoalBTU.

Сгенерируйте код со структурой хранилища данных

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

  2. В отчете о генерации кода просмотрите файл ex_bus_struct_in_code_types.h. Код определяет структуру, которая соответствует типу шины Raw_BTU_Rate.

    typedef struct {
      real_T BioBTU;
      real_T GasBTU;
      real_T CoalBTU;
    } Raw_BTU_Rate;
    
  3. Просмотрите файл ex_bus_struct_in_code.c. Код представляет хранилище данных с глобальной переменной Raw_BTU_Data типа структуры Raw_BTU_Rate. В функции шага модели код присваивает данные из вычисленных сигналов полям глобальной переменной Raw_BTU_Data.

Похожие темы