Если ваша модель имеет оптимальные настройки параметров для удаления копий данных, вы можете удалить дополнительные копии данных при помощи Simulink.Signal
объекты для задания повторного использования буфера. После изучения сгенерированного кода и отчета Static Code Metrics Report и определения областей, где, по вашему мнению, повторное использование буфера возможно, вы задаете объекты сигнала на сигнальных линиях.
Можно задать повторное использование буфера для сигналов, которые включают пару корневых входных и выходных сигналов. Можно также задать повторное использование буфера только на паре корневых сигналов inport и outport. Эта оптимизация уменьшает потребление ПЗУ и ОЗУ, потому что в сгенерированном коде меньше глобальных переменных и копий данных. Скорость выполнения кода также увеличивается.
rtwdemo_reusable_csc модели содержит непереиспользуемую подсистему DeltaSubsystem
и блок MATLAB Function Downsample
. DeltaSubsystem
содержит блоки MATLAB Function DeltaX
и DeltaY
.
model ='rtwdemo_reusable_csc';
open_system(model);
В галерее галерей Apps в разделе Генерация кода нажмите Embedded Coder. Откроется вкладка Кода С.
Чтобы открыть редактор Отображения, выберите Code Interface > Individual Element Code Mappings.
В модели выберите RCSC_REAL
сигнальная линия. Чтобы просмотреть этот сигнал или любой сигнал в редакторе Отображения, на вкладке Signals/States, нажмите кнопку Add selected signals to code mappings.
Для строки, которая представляет сигнальную линию, смотрите столбец «Класс памяти». Объект сигнала использует класс памяти Reusable
, что означает, что объект появляется в сгенерированном коде как глобальная переменная с именем RCSC_REAL
.
В модели перейдите в DeltaSubsystem
подсистема.
Выберите RCSC_REAL
сигнальная линия в этой подсистеме. Этот сигнал также разрешается к объекту сигнала в базовом рабочем пространстве.
С Reusable
класс памяти, сгенерированный код может хранить выходы Complex to Real-Imag
блок (на корневом уровне модели) и выход DeltaX
блок (в подсистеме) в RCSC_REAL
глобальная переменная.
Создайте модель.
currentDir = pwd; [~,cgDir] = rtwdemodir(); slbuild(model);
### Starting build procedure for: rtwdemo_reusable_csc ### Successful completion of build procedure for: rtwdemo_reusable_csc Build Summary Top model targets built: Model Action Rebuild Reason ===================================================================================================== rtwdemo_reusable_csc Code generated and compiled Code generation information file does not exist. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 16.799s
Для повторного использования буфера, rtwdemo_reusable_csc.c
файл содержит следующие глобальные переменные:
static real_T RCSC_IMAG[1048576];
static real_T RCSC_IMAG2[262144];
static real_T RCSC_REAL[1048576];
static real_T RCSC_REAL2[262144];
The rtwdemo_reusable_csc.c
файл содержит этот код:
cfile = fullfile(cgDir,... 'rtwdemo_reusable_csc_ert_rtw','rtwdemo_reusable_csc.c'); rtwdemodbtype(cfile,... '/* Output and update for atomic system: ''<Root>/DeltaSubsystem'' */',... '/* Output and update for atomic system: ''<Root>/Downsample'' */',1,0); rtwdemodbtype(cfile,... '/* Model step function */','/* Model initialize function */',1,0);
/* Output and update for atomic system: '<Root>/DeltaSubsystem' */ static void DeltaSubsystem(void) { /* SignalConversion generated from: '<S1>/DeltaX' incorporates: * MATLAB Function: '<S1>/DeltaX' */ DeltaX((&(RCSC_REAL2[0])), (&(RCSC_IMAG2[0])), (&(RCSC_REAL[0])), (&(RCSC_IMAG[0]))); /* SignalConversion generated from: '<S1>/DeltaY' incorporates: * MATLAB Function: '<S1>/DeltaY' */ DeltaY((&(RCSC_REAL[0])), (&(RCSC_IMAG[0])), (&(RCSC_REAL2[0])), (&(RCSC_IMAG2[0]))); } /* Model step function */ void rtwdemo_reusable_csc_step(void) { int32_T i; /* ComplexToRealImag: '<Root>/Complex to Real-Imag' incorporates: * Inport: '<Root>/ComplexData' */ for (i = 0; i < 1048576; i++) { RCSC_REAL[i] = rtU.ComplexData[i].re; RCSC_IMAG[i] = rtU.ComplexData[i].im; } /* End of ComplexToRealImag: '<Root>/Complex to Real-Imag' */ /* MATLAB Function: '<Root>/Downsample' */ Downsample((&(RCSC_REAL[0])), (&(RCSC_IMAG[0])), (&(RCSC_REAL2[0])), (&(RCSC_IMAG2[0]))); /* Outputs for Atomic SubSystem: '<Root>/DeltaSubsystem' */ DeltaSubsystem(); /* End of Outputs for SubSystem: '<Root>/DeltaSubsystem' */ /* Outport: '<Root>/Out1' incorporates: * RealImagToComplex: '<Root>/Real-Imag to Complex' * SignalConversion generated from: '<S1>/DeltaY' * */ for (i = 0; i < 261121; i++) { rtY.Out1[i].re = RCSC_REAL2[i]; rtY.Out1[i].im = RCSC_IMAG2[i]; } /* End of Outport: '<Root>/Out1' */ }
Переменные RCSC_REAL
и RCSC_IMAG
удерживать выходы блока Complex to Real-Image и DeltaX
. Эти переменные содержат входы в DeltaY
блок. Переменные RCSC_REAL2
и RCSC_IMAG2
удерживать выходы Downsample
и DeltaY
. Эти переменные содержат входы в DeltaX
блок. Путем чередования буферов таким образом, вы устраняете глобальные переменные в сгенерированном коде.
Чтобы удалить объекты сигнала из сигнальных линий и перегенерировать код, в Командном окне MATLAB введите следующие команды:
portHandles = get_param(... 'rtwdemo_reusable_csc/Complex to Real-Imag','portHandles'); set_param(portHandles.Outport(1),'MustResolveToSignalObject','off'); set_param(portHandles.Outport(2),'MustResolveToSignalObject','off'); portHandles = get_param(... 'rtwdemo_reusable_csc/Downsample','portHandles'); set_param(portHandles.Outport(1),'MustResolveToSignalObject','off'); set_param(portHandles.Outport(2),'MustResolveToSignalObject','off'); portHandles = get_param(... 'rtwdemo_reusable_csc/DeltaSubsystem/DeltaX','portHandles'); set_param(portHandles.Outport(1),'MustResolveToSignalObject','off'); set_param(portHandles.Outport(2),'MustResolveToSignalObject','off'); portHandles = get_param(... 'rtwdemo_reusable_csc/DeltaSubsystem/DeltaY','portHandles'); set_param(portHandles.Outport(1),'MustResolveToSignalObject','off'); set_param(portHandles.Outport(2),'MustResolveToSignalObject','off'); slbuild(model);
### Starting build procedure for: rtwdemo_reusable_csc ### Successful completion of build procedure for: rtwdemo_reusable_csc Build Summary Top model targets built: Model Action Rebuild Reason ==================================================================================== rtwdemo_reusable_csc Code generated and compiled Generated code was out of date. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 11.54s
The rtwdemo_reusable_csc.c
файл теперь содержит этот код.
cfile = fullfile(cgDir,... 'rtwdemo_reusable_csc_ert_rtw','rtwdemo_reusable_csc.c'); rtwdemodbtype(cfile,... '/* Output and update for atomic system: ''<Root>/DeltaSubsystem'' */',... '/* Output and update for atomic system: ''<Root>/Downsample'' */',1,0); rtwdemodbtype(cfile,... '/* Model step function */','/* Model initialize function */',1,0);
/* Output and update for atomic system: '<Root>/DeltaSubsystem' */ static void DeltaSubsystem(void) { /* MATLAB Function: '<S1>/DeltaX' */ DeltaX(rtDWork.z2, rtDWork.z1, rtDWork.z1_m, rtDWork.z2_c); /* MATLAB Function: '<S1>/DeltaY' */ DeltaY(rtDWork.z1_m, rtDWork.z2_c, &rtDWork.z1[0], &rtDWork.z2[0]); } /* Model step function */ void rtwdemo_reusable_csc_step(void) { int32_T i; /* ComplexToRealImag: '<Root>/Complex to Real-Imag' incorporates: * Inport: '<Root>/ComplexData' */ for (i = 0; i < 1048576; i++) { rtDWork.RCSC_REAL[i] = rtU.ComplexData[i].re; rtDWork.RCSC_IMAG[i] = rtU.ComplexData[i].im; } /* End of ComplexToRealImag: '<Root>/Complex to Real-Imag' */ /* MATLAB Function: '<Root>/Downsample' */ Downsample(rtDWork.RCSC_REAL, rtDWork.RCSC_IMAG, rtDWork.z2, rtDWork.z1); /* Outputs for Atomic SubSystem: '<Root>/DeltaSubsystem' */ DeltaSubsystem(); /* End of Outputs for SubSystem: '<Root>/DeltaSubsystem' */ /* Outport: '<Root>/Out1' incorporates: * RealImagToComplex: '<Root>/Real-Imag to Complex' */ for (i = 0; i < 261121; i++) { rtY.Out1[i].re = rtDWork.z1[i]; rtY.Out1[i].im = rtDWork.z2[i]; } /* End of Outport: '<Root>/Out1' */ }
Сгенерированный код содержит две дополнительные глобальные переменные для хранения входных и выходных входов блоков.
Примечание: Вы можете задать повторное использование буфера на сигналах, которые генератор кода не может реализовать. В этих случаях используйте две диагностики, чтобы задать тип сообщения, которое отображается в модели. В диалоговом окне Параметров конфигурации эти диагностики: Обнаружение неиспользуемых пользовательских классов памяти и Обнаружение неоднозначных конечных значений пользовательского класса памяти.
bdclose(model) rtwdemoclean; cd(currentDir)
Чтобы повторно использовать сигнал блока Unit Delay или Delay, используйте ту же спецификацию переиспользуемого класса памяти для пары аргументов входа и состояния или пару аргументов выхода и состояния блока Unit Delay или Delay. Для блоков Delay необходимо задать параметр Delay length равным 1
и Начальное условие > Источник к Dialog
. Чтобы получить доступ к этим параметрам, в модели откройте Property Inspector и щелкните блок в модели.
Эти ограничения применяются к модели, в которой вы задаете повторное использование буфера для пары корневых сигналов inport и outport:
Порты выхода не могут быть условными.
Если генератор кода не может повторно использовать тот же буфер в верхней модели, сгенерированный код содержит дополнительные буферы. Если модель верхней части является образцом модели, генератор кода сообщает об ошибке. Чтобы устранить ошибку, удалите спецификацию Simulink.signal из сигнала, который соединяется с выходным портом.
Когда вы запускаете исполняемый файл, который производит генератор кода, и вы повторно используете пару корневых сигналов inport и outport, когда корневое входное значение равно нулю, корневое выходное значение также должно быть нулем. Если выходное значение ненулевое, и вы повторно используете сигналы, то результаты симуляции могут отличаться от результатов, которые создает исполняемый файл.
Может быть симуляция и несоответствие генерации кода, когда вы присваиваете тот же класс памяти Reusable паре корневых входных и корневых выходных сигналов. Это несоответствие происходит, когда блок Assignment управляет блоком Root Outport, и блок Assignment не присваивает значение каждому элементу выхода сигнала, потому что порт Y блока Assignment не активен. На этом изображении показана модель, в которой происходит несовпадение:
Во время симуляции неписанные выходные значения блока Assignment равны нулю. Во время генерации кода неписанные выходные значения совпадают с входными.
Эти ограничения применяются к модели, в которой вы задаете повторное использование буфера для сигналов:
Сигналы, которые вы задаете для повторного использования, должны иметь совпадающие типы данных и частот дискретизации.
Для пользовательского повторного использования буфера блоки, которые изменяют сигнал, заданный для повторного использования, должны выполняться перед блоками, которые используют исходное значение сигналов. Иногда генератору кода приходится изменять порядок операции блока, чтобы могло произойти повторное использование буфера. Для моделей, в которых генератор кода не может переупорядочить операции блока, повторное использование буфера не происходит.
Для моделей, в которых генератор кода переупорядочивает блок операции так, что Simulink.Signal
повторное использование может произойти, вы можете наблюдать различие в отсортированном порядке. На вкладке Отладки в разделе Diagnostics выберите раскрывающуюся стрелу Information Overlays. В разделе « Блоках» диалогового окна выберите «Порядок выполнения». Чтобы отобразить отсортированный порядок выполнения во время симуляции, на вкладке Modeling, выберите Update Model. Чтобы отобразить порядок выполнения в сгенерированном коде, на вкладке Код С, выберите Build Model.
Можно задать повторное использование буфера для цепи переиспользуемых подсистем, пока эти подсистемы не будут повторно использоваться нигде в модели.