Интегрируйте сгенерированный код при помощи рабочего процесса перекрестного релиза

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

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

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

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

model = 'rtwdemo_crossrelease_counter';
close_system(model,0)
load_system(model)
set_param(model, 'SimulationCommand', 'update');
open_system(model)
rtwbuild(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 6.3592s

Идентифицируйте папку сборки, которая содержит сгенерированный код.

buildFolder = RTW.getBuildDir(model).BuildDirectory;

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

previousSharedCodeFolder = RTW.getBuildDir(model).SharedUtilsTgtDir;

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

  1. На вкладке Simulation, в Разделе файла, выбирают Save> Previous Version.

  2. В Сохранении как поле типа задайте релиз и тип модели.

  3. Нажмите Save.

  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/R2020b:

    rtwtypes.h

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

Импортируйте код

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

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

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

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

Создайте блок SIL перекрестного релиза.

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

Включите перекрестный релиз блок 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_R2020b_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_R2020b_sil
rtw.connectivity.HostLauncher: started executable with host process identifier 113008
rtw.connectivity.HostLauncher: stopped executable with host process identifier 113008
### Stopping SIL simulation for component: rtwdemo_crossrelease_counter_R2020b_sil

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

Исходная модель для ссылок блока SIL перекрестного релиза два настраиваемых параметра, которыми управляет Simulink.Parameter object s в базовом рабочем пространстве. Используйте эти параметры, чтобы изменить поведение 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_R2020b_sil
rtw.connectivity.HostLauncher: started executable with host process identifier 113044
rtw.connectivity.HostLauncher: stopped executable with host process identifier 113044
### Stopping SIL simulation for component: rtwdemo_crossrelease_counter_R2020b_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);

Сгенерируйте код.

rtwbuild(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 8.8847s

Исследуйте вызов импортированного кода

Чтобы исследовать блочный код перекрестного релиза в рамках типового кодекса интегрирования, используйте 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_R2020b_sil does not exist.  

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 6.3704s
### 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