exponenta event banner

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

В этом примере показано, как повторно использовать ранее созданный код путем создания блока программного обеспечения в цикле (SIL) перекрестного выпуска и включения блока в интеграционную модель. Дополнительные сведения о рабочем процессе см. в разделе Интеграция кода для нескольких версий.

Создание кода из модели

В рабочем процессе интеграции кода кросс-версии создается блок «программное обеспечение в цикле» (SIL) или «процессор в цикле» (PIL) из ранее сгенерированного кода.

В этом примере используется сгенерированный код текущей версии.

model = 'rtwdemo_crossrelease_counter';
close_system(model,0)
load_system(model)
set_param(model, 'SimulationCommand', 'update');
open_system(model)
slbuild(model);
### Starting build procedure for: rtwdemo_crossrelease_counter
### Successful completion of code generation for: rtwdemo_crossrelease_counter

Build Summary

Top model targets built:

Model                         Action          Rebuild Reason                                    
================================================================================================
rtwdemo_crossrelease_counter  Code generated  Code generation information file does not exist.  

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

Укажите папку построения, содержащую созданный код.

buildFolder = RTW.getBuildDir(model).BuildDirectory;

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

previousSharedCodeFolder = RTW.getBuildDir(model).SharedUtilsTgtDir;

Для повторного использования созданного кода из предыдущей версии:

  1. На вкладке Моделирование в разделе Файл выберите Сохранить > Предыдущая версия.

  2. В поле Тип сохранения укажите выпуск и тип модели.

  3. Нажмите кнопку Сохранить.

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

  5. Установка значения buildFolder в местоположение кода, созданного в предыдущей версии.

  6. Установка значения previousSharedCodeFolder в расположение общих утилит, созданных в предыдущей версии.

Управление общим кодом

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

sharedCodeRepo = 'SharedCodeRepo';
mkdir(sharedCodeRepo);
sharedCodeUpdate(previousSharedCodeFolder, sharedCodeRepo, 'Interactive', false);
The following files will be copied from slprj/ert/_sharedutils to SharedCodeRepo/R2021a:

    rtwtypes.h

Files copied from slprj/ert/_sharedutils to SharedCodeRepo/R2021a.

Код импорта

Загрузите интеграционную модель.

integrationModel = 'rtwdemo_crossrelease_integration';
close_system(integrationModel, 0);
load_system(integrationModel);

Измените набор конфигурации Simulink так, чтобы он ссылался на существующую библиотеку общего кода.

cs = getActiveConfigSet(integrationModel);
set_param(cs, 'ExistingSharedCode', fullfile(pwd, sharedCodeRepo));

Создайте блок SIL cross-release.

blockHandle = crossReleaseImport(buildFolder, cs, 'SimulationMode', 'SIL');
### Starting import process for component: rtwdemo_crossrelease_counter_R2021a
### Starting build process for SIL block: rtwdemo_crossrelease_counter_R2021a

Включение блока SIL для всех версий в интеграционную модель

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

srcBlock = getfullname(blockHandle);
dstBlock = [integrationModel, '/', 'Counter'];
pil_block_replace(srcBlock, dstBlock)
open_system(integrationModel)
Successfully swapped the following blocks: 

untitled/rtwdemo_crossrelease_counter_R2021a_sil
rtwdemo_crossrelease_integration/Counter


Моделирование интеграционной модели

Выполните моделирование интеграционной модели.

sim(integrationModel)
### Preparing to start SIL block simulation: rtwdemo_crossrelease_integration/Counter ...
### Starting SIL simulation for component: rtwdemo_crossrelease_counter_R2021a_sil
rtw.connectivity.HostLauncher: started executable with host process identifier 96717
rtw.connectivity.HostLauncher: stopped executable with host process identifier 96717
### Stopping SIL simulation for component: rtwdemo_crossrelease_counter_R2021a_sil

Настройка параметров

Исходная модель для блока SIL перекрестного выпуска ссылается на два настраиваемых параметра, которыми управляют объекты Simulink.Parameter. Эти параметры используются для изменения поведения моделирования SIL.

countUpper.Value = 30;
countLower.Value = 20;
yout_retuned = sim(integrationModel, 'ReturnWorkspaceOutputs', 'on');
### Preparing to start SIL block simulation: rtwdemo_crossrelease_integration/Counter ...
### Starting SIL simulation for component: rtwdemo_crossrelease_counter_R2021a_sil
rtw.connectivity.HostLauncher: started executable with host process identifier 96776
rtw.connectivity.HostLauncher: stopped executable with host process identifier 96776
### Stopping SIL simulation for component: rtwdemo_crossrelease_counter_R2021a_sil

Конфигурирование класса хранения для сигналов в интеграционной модели

Настройка:

  • Имена сигналов в интеграционной модели соответствуют именам, используемым в импортированном коде.

  • Дополнительные классы хранения.

В этом случае ticks входные данные и count выходные данные реализуются через ImportedExtern класс хранения в импортированном коде. Если класс памяти для сигналов, подключенных к входному и выходному портам блока кросс-освобождения в интеграционной модели, равен ExportedGlobal, интеграционная модель должна содержать определения переменных.

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

hLines = get_param(dstBlock, 'LineHandles');

% Use the code mappings API to configure the storage class on the signals.
cm = coder.mapping.api.get(integrationModel);
ticksPortHandle = get(hLines.Inport(1), 'SrcPortHandle');
set(ticksPortHandle, 'Name', 'ticks');
addSignal(cm, ticksPortHandle);
setSignal(cm, ticksPortHandle, 'StorageClass', 'ExportedGlobal');

countPortHandle = get(hLines.Outport(1), 'SrcPortHandle');
set(countPortHandle, 'Name', 'count');
addSignal(cm, countPortHandle);
setSignal(cm, countPortHandle, 'StorageClass', 'ExportedGlobal');

Настройка класса хранения для параметров и памяти хранилища данных в интеграционной модели

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

resetSignal.CoderInfo.StorageClass = 'ExportedGlobal';
countLower.CoderInfo.StorageClass = 'ExportedGlobal';
countUpper.CoderInfo.StorageClass = 'ExportedGlobal';

Создание кода на основе интеграционной модели

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

if isfolder(RTW.getBuildDir(integrationModel).SharedUtilsTgtDir)
    rmdir(RTW.getBuildDir(integrationModel).SharedUtilsTgtDir, 's');
end

Удалите область и соединительную линию, которые не влияют на создание кода.

scopeBlock = [integrationModel, '/', 'Scope'];
hScopeLines = get_param(scopeBlock, 'LineHandles');
hScopeLine = hScopeLines.Inport(1);
assert(strcmp(get(hScopeLine, 'SegmentType'), 'branch'));
delete_line(hScopeLine);
delete_block(scopeBlock);

Создать код.

slbuild(integrationModel);
### Starting build procedure for: rtwdemo_crossrelease_integration
### Successful completion of code generation for: rtwdemo_crossrelease_integration

Build Summary

Top model targets built:

Model                             Action          Rebuild Reason                                    
====================================================================================================
rtwdemo_crossrelease_integration  Code generated  Code generation information file does not exist.  

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

Проверка вызова импортированного кода

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

rtwtrace(dstBlock);

Тестовый код, созданный на основе интеграционной модели

Выполните моделирование модели интеграции с использованием программного обеспечения верхнего уровня в цикле (SIL). При моделировании запускается код, созданный из интеграционной модели, которая вызывает импортированный код.

Зарегистрируйте выходные данные моделирования в рабочей области.

set_param(integrationModel, 'SimulationMode', 'software-in-the-loop (sil)');
yout_SIL = sim(integrationModel, 'ReturnWorkspaceOutputs', 'on');
plot(yout_SIL.yout{1}.Values);
### Starting build procedure for: rtwdemo_crossrelease_integration
### Successful completion of build procedure for: rtwdemo_crossrelease_integration

Build Summary

Top model targets built:

Model                             Action                       Rebuild Reason                                                      
===================================================================================================================================
rtwdemo_crossrelease_integration  Code generated and compiled  S-function rtwdemo_crossrelease_counter_R2021a_sil does not exist.  

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 6.3114s
### Preparing to start SIL simulation ...
Building with 'gcc'.
MEX completed successfully.
### Updating code generation report with SIL files ...
### Starting SIL simulation for component: rtwdemo_crossrelease_integration
### Stopping SIL simulation for component: rtwdemo_crossrelease_integration

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

Сравните выходные данные моделирования, в котором только импортированный код выполнялся в режиме SIL, с выходными данными моделирования, в котором интеграционная модель выполнялась как модель верхнего уровня в режиме SIL.

max(abs(yout_SIL.yout{1}.Values.Data - yout_retuned.yout{1}.Values.Data))
ans =

  uint8

   0