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

О хранилищах данных

Хранилище данных содержит данные, которые доступны в иерархии модели в или ниже уровня, на котором задано хранилище данных. Хранилища данных могут позволить подсистемам и моделям, на которые ссылаются, осуществлять обмен данными, не имея необходимость использовать порты I/O, чтобы передать данные от уровня до уровня. Смотрите Хранилища данных с Блоками памяти Хранилища данных для получения информации о хранилищах данных в 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. В диалоговом окне Create New Data, набор Value к Simulink.Signal. Опционально, используйте Location выпадающий список, чтобы выбрать рабочую область для хранения получившегося Simulink.Signal объект.

  6. Нажмите Create. 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 (когда Код, Сопоставляющий Редактор, задает 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 является невиртуальным блоком, который копирует значение хранилища данных к его буферу вывода, когда это выполняется. Поскольку значение буферизуется, нисходящие блоки, соединенные с выходом чтения хранилища данных, используют то же значение, даже если блок Data Store Write обновляет хранилище данных промежуточное выполнение двух из нисходящих блоков.

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

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

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

  2. Блок Abs1 использует буферизированный выход Чтения Хранилища данных.

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

  4. Блок Abs использует буферизированный выход Чтения Хранилища данных.

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

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

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

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

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

  3. Блок Sum добавляет выход Атомарной подсистемы к выходу Чтения Хранилища данных.

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

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

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

Хранилища данных, разделяемые экземплярами допускающей повторное использование модели

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

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

  • Если у вас есть Embedded Coder®, чтобы ограничить получают доступ таким образом, что только код, сгенерированный из модели, может использовать хранилище данных, сконфигурируйте хранилище данных, чтобы появиться как static путем применения класса памяти FileScope. Для получения дополнительной информации о FileScope и другие классы памяти, смотрите, Выбирают Storage Class for Controlling Data Representation in Generated Code (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. Откройте инструмент Bus Editor.

    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 в каждой подсистеме.

    • В каждом диалоговом окне блока Data Store Write, набор 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.

Похожие темы