Установите типы данных с помощью Min/Max Instrumentation

В этом примере показано, как задать типы данных с фиксированной точкой с помощью кода MATLAB ® для логгирования min/max и с помощью инструментов для предложения типов данных.

Функции, которые вы будете использовать:

Тестируемый модуль

Функция, которую вы преобразовываете в фиксированную точку в этом примере, является транспонированным фильтром 2 прямой формы второго порядка. Вы можете заменить свою собственную функцию вместо этой, чтобы воспроизвести эти шаги в вашей собственной работе.

function [y,z] = fi_2nd_order_df2t_filter(b,a,x,y,z)
    for i=1:length(x)
        y(i) = b(1)*x(i) + z(1);
        z(1) = b(2)*x(i) + z(2) - a(2) * y(i);
        z(2) = b(3)*x(i)        - a(3) * y(i);
    end
end

Чтобы функция MATLAB ® была инструментализирована, она должна быть подходящей для генерации кода. Для получения информации о генерации кода смотрите страницу с описанием для buildInstrumentedMex. Лицензия Coder™ MATLAB ® не требуется для использования buildInstrumentedMex.

В этой функции переменные y и z используются как входы, так и выходы. Это важный шаблон, потому что:

  • Можно задать тип данных y и z вне функции, что позволяет вам повторно использовать функцию как для типов с фиксированной точкой, так и для типов с плавающей точкой.

  • Сгенерированный код C создаст y и z как ссылки в списке аргументов функции. Для получения дополнительной информации об этом шаблоне см. документацию по разделу Генерация кода из MATLAB ® > Руководство пользователя > Генерация эффективного и переиспользуемого кода > Генерация эффективного кода > Исключение избыточных копий входных параметров функции.

Запустите следующий код, чтобы скопировать тестовую функцию во временную директорию, чтобы этот пример не мешал вашей собственной работе.

tempdirObj = fidemo.fiTempdir('fi_instrumentation_fixed_point_filter_demo');
copyfile(fullfile(matlabroot,'toolbox','fixedpoint','fidemos','+fidemo',...
                  'fi_2nd_order_df2t_filter.m'),'.','f');

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

FIPREF_STATE = get(fipref);
reset(fipref)

Типы данных, определяемые требованиями проекта

В этом примере требования проекта определяют тип данных входов x. Эти требования являются подписанными, 16-битными и дробными.

N = 256;
x = fi(zeros(N,1),1,16,15);

Требования проекта также определяют математику с фиксированной точкой для цели DSP с 40-битным аккумулятором. Этот пример использует округление пола и переполнение переноса для создания эффективного сгенерированного кода.

F = fimath('RoundingMethod','Floor',...
           'OverflowAction','Wrap',...
           'ProductMode','KeepLSB',...
           'ProductWordLength',40,...
           'SumMode','KeepLSB',...
           'SumWordLength',40);

Следующие коэффициенты соответствуют lowpass второго порядка, созданному

[num,den] = butter(2,0.125)

Значения коэффициентов влияют на область значений значений, которые будут назначены выходу фильтра и состояниям.

num = [0.0299545822080925  0.0599091644161849  0.0299545822080925];
den = [1                  -1.4542435862515900  0.5740619150839550];

Тип данных коэффициентов, определяемых требованиями проекта, задается как 16-битный размер слова и масштабируется до наилучшей точности. Шаблон для создания fi объекты из постоянных коэффициентов:

1. Приведите коэффициенты к fi объекты, использующие по умолчанию параметры переполнения от скругления до ближайшего и насыщающие, что дает коэффициентам лучшую точность.

2. Прикрепить fimath с округлением пола и переносом параметров переполнения для управления арифметикой, что приводит к более эффективному коду С

b = fi(num,1,16); b.fimath = F;
a = fi(den,1,16); a.fimath = F;

Жесткий код фильтра коэффициентов в реализацию этого фильтра путем передачи их как констант в buildInstrumentedMex команда.

B = coder.Constant(b);
A = coder.Constant(a);

Типы данных, определяемые значениями коэффициентов и входных параметров

Значения коэффициентов и значения входов определяют типы данных выхода y и вектор состояния z. Создайте их с масштабированным типом данных double, чтобы их значения достигли полной области значений, и вы можете идентифицировать потенциальные переполнения и предложить типы данных.

yisd = fi(zeros(N,1),1,16,15,'DataType','ScaledDouble','fimath',F);
zisd = fi(zeros(2,1),1,16,15,'DataType','ScaledDouble','fimath',F);

Инструментируйте функцию MATLAB ® как масштабированно-двойную MEX-функцию

Чтобы инструментализировать код MATLAB ®, вы создаете MEX-функцию из функции MATLAB ® с помощью buildInstrumentedMex команда. Входы для buildInstrumentedMex являются такими же, как и входы в fiaccel, но buildInstrumentedMex не имеет fi-объектные ограничения. Область выхода buildInstrumentedMex является MEX-функцией с вставленным инструментированием, поэтому при запуске MEX-функции моделируемые минимальное и максимальное значения записываются для всех именованных переменных и промежуточных значений.

Используйте '-o' опция для присвоения имени MEX-функции. Если вы не используете '-o' опция, тогда MEX-функция является именем функции MATLAB ® с '_mex' приложенный. Можно также назвать MEX-функцию так же, как и функцию MATLAB ®, но необходимо помнить, что MEX-функции имеют приоритет над функциями MATLAB ®, и поэтому изменения функции MATLAB ® не будут запускаться до тех пор, пока MEX-функция не будет повторно сгенерирована, или MEX-функция не будет удалена и очищена.

buildInstrumentedMex fi_2nd_order_df2t_filter ...
    -o filter_scaled_double ...
    -args {B,A,x,yisd,zisd}

Испытательный стенд с входом щебета

Испытательный стенд для этой системы настроен для запуска щебета и шаговых сигналов. В целом испытательные стенды для систем должны охватывать широкую область значений входных сигналов.

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

t = linspace(0,1,N);       % Time vector from 0 to 1 second
f1 = N/2;                  % Target frequency of chirp set to Nyquist
xchirp = sin(pi*f1*t.^2);  % Linear chirp from 0 to Fs/2 Hz in 1 second
x(:) = xchirp;             % Cast the chirp to fixed-point

Запустите инструментальную MEX-функцию, чтобы записать минимальные/максимальные значения

Инструментальная MEX-функция должна быть запущена, чтобы записать минимальное и максимальное значения для этого запуска симуляции. Последующие запуски накапливают результаты инструментирования, пока они не будут удалены с помощью clearInstrumentationResults.

Обратите внимание, что коэффициенты числителя и знаменателя были скомпилированы как константы, поэтому они не предоставляются как вход в сгенерированную MEX-функцию.

ychirp = filter_scaled_double(x,yisd,zisd);

График фильтрованного щебета-сигнала показывает lowpass фильтра с этими конкретными коэффициентами. Пропускают низкие частоты и ослабляют более высокие частоты.

clf
plot(t,x,'c',t,ychirp,'bo-')
title('Chirp')
legend('Input','Scaled-double output')
figure(gcf); drawnow;

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

The showInstrumentationResults команда отображает отчет генерации кода с инструментальными значениями. Вход в showInstrumentationResults - имя инструментальной MEX-функции, для которого необходимо отобразить результаты.

Это список опций для showInstrumentationResults команда:

  • -defaultDT T Тип данных по умолчанию, который предлагается для doubles, где T является numerictype объект или одна из строк {remainFloat, double, single, int8, int16, int32, int64, uint8, uint16, uint32, uint64}. Значение по умолчанию является remainFloat.

  • -nocode Не отображать код MATLAB в отчете печати. Отображать только записанные таблицы переменных. Эта опция имеет эффект только в комбинацию с опцией -printable.

  • -optimizeWholeNumbers Оптимизируйте размер слова переменных, чьи журналы симуляции min/max указывают, что они всегда были целыми числами.

  • -percentSafetyMargin N Запас прочности для симуляции min/max, где N представляет собой процентное значение.

  • -printable Создайте отчет для печати и откройте его в системном браузере.

  • -proposeFL Предложите длины дробей для заданных размеров слова.

  • -proposeWL Предложите размеры слова для заданных длин дробей.

Потенциальные переполнения отображаются только для fi объекты с типом данных Scaled Double.

Этот конкретный проект предназначен для DSP, где размеры слова фиксированы, поэтому используйте proposeFL флаг для предложения длин дробей.

showInstrumentationResults filter_scaled_double -proposeFL

Наведите на выражения или переменные в отчете генерации кода с инструментами, чтобы увидеть минимальное и максимальное значения симуляции. В этом проекте входы падают между -1 и + 1, и значения всех переменных и промежуточных результатов также падают между -1 и + 1. Это предполагает, что типы данных все могут быть дробными (длина дроби на один бит меньше, чем размер слова). Однако это не всегда будет верно для этой функции для других видов входов, и важно протестировать многие типы входов перед установкой окончательных типов данных с фиксированной точкой.

Испытательный стенд с пошаговым входом

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

xstep = [ones(N/2,1);-ones(N/2,1)];
x(:) = xstep;

Запуск инструментальной MEX-функции с помощью шага ввода

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

ystep = filter_scaled_double(x,yisd,zisd);

clf
plot(t,x,'c',t,ystep,'bo-')
title('Step')
legend('Input','Scaled-double output')
figure(gcf); drawnow;

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

Даже при том, что входы для шага и щебета входов полны области значений как обозначено x в 100-процентной области значений тока в отчете о генерации кода с инструментами, вход шага вызывает переполнение, в то время как вход щебета не сделал. Это является иллюстрацией необходимости иметь много различных входов для вашего испытательного стенда. Для целей этого примера использовались только два входов, но реальные испытательные стенды должны быть более тщательными.

showInstrumentationResults filter_scaled_double -proposeFL

Применение предлагаемых свойств фиксированной точки

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

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

yi = fi(zeros(N,1),1,16,14,'fimath',F);
zi = fi(zeros(2,1),1,16,14,'fimath',F);

Инструментируйте функцию MATLAB ® как MEX-функцию с фиксированной точкой

Создайте инструментальную MEX-функцию с фиксированной точкой с помощью входов с фиксированной точкой и buildInstrumentedMex команда.

buildInstrumentedMex fi_2nd_order_df2t_filter ...
    -o filter_fixed_point ...
    -args {B,A,x,yi,zi}

Проверьте алгоритм с фиксированной точкой

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

Валидация с вход щебета

Запустите алгоритм с фиксированной точкой с входом, чтобы подтвердить проект.

x(:) = xchirp;
[y,z] = filter_fixed_point(x,yi,zi);
[ysd,zsd] = filter_scaled_double(x,yisd,zisd);
err = double(y) - double(ysd);

Сравните выходы с фиксированной точкой с двойными выходами, чтобы убедиться, что они соответствуют вашим проектам критериям.

clf
subplot(211);plot(t,x,'c',t,ysd,'bo-',t,y,'mx')
xlabel('Time (s)');
ylabel('Amplitude')
legend('Input','Scaled-double output','Fixed-point output');
title('Fixed-Point Chirp')
subplot(212);plot(t,err,'r');title('Error');xlabel('t'); ylabel('err');
figure(gcf); drawnow;

Проверьте переменные и промежуточные результаты, чтобы убедиться, что значения min/max находятся в области значений.

showInstrumentationResults filter_fixed_point

Валидация с помощью входных параметров шага

Запустите алгоритм с фиксированной точкой с входом, чтобы подтвердить проект.

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

clearInstrumentationResults filter_fixed_point

Запустите шаговый вход через фильтр с фиксированной точкой и сравните с выходом масштабированного двойного фильтра.

x(:) = xstep;
[y,z] = filter_fixed_point(x,yi,zi);
[ysd,zsd] = filter_scaled_double(x,yisd,zisd);
err = double(y) - double(ysd);

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

clf
subplot(211);plot(t,x,'c',t,ysd,'bo-',t,y,'mx')
title('Fixed-Point Step');
legend('Input','Scaled-double output','Fixed-point output')
subplot(212);plot(t,err,'r');title('Error');xlabel('t'); ylabel('err');
figure(gcf); drawnow;

Проверьте переменные и промежуточные результаты, чтобы убедиться, что значения min/max находятся в области значений.

showInstrumentationResults filter_fixed_point

Запустите следующий код, чтобы восстановить глобальные состояния.

fipref(FIPREF_STATE);
clearInstrumentationResults filter_fixed_point
clearInstrumentationResults filter_scaled_double
clear fi_2nd_order_df2t_filter_fixed_instrumented
clear fi_2nd_order_df2t_filter_float_instrumented

Запустите следующий код, чтобы удалить временную директорию.

tempdirObj.cleanUp;
%#ok<*ASGLU>