Интеграция сгенерированного кода с помощью рабочего процесса Cross-Release

Этот пример показывает, как повторно использовать ранее сгенерированный код путем создания блока cross-release software-in-the-loop (SIL) и включения блока в интеграционную модель. Дополнительные сведения о рабочем процессе см. в разделе Интегрировании между выпусками кода.

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

В рабочем процессе интегрирования кросс-release кода вы создаете цикл» (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. На вкладке Simulation, в Разделе файла, выберите Save > Previous Version.

  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));

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

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

Включите блок Cross-Release SIL в Интегрирование модель

Чтобы заменить блок в модели интегрирования блоком cross-release, используйте 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

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

Исходная модель для блока cross-release 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 класс памяти в импортированном коде. Если класс памяти для сигналов, соединенных с портами входа и выхода блока cross-release в модели интегрирования, 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

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