В этом примере показано, как задать типы данных с фиксированной точкой с помощью кода MATLAB ® для логгирования min/max и с помощью инструментов для предложения типов данных.
Функции, которые вы будете использовать:
buildInstrumentedMex
- Создайте функцию MEX с включённым инструментированием
showInstrumentationResults
- Показать результаты инструментирования
clearInstrumentationResults
- Очистить результаты инструментирования
Функция, которую вы преобразовываете в фиксированную точку в этом примере, является транспонированным фильтром 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 ® с помощью 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-функция должна быть запущена, чтобы записать минимальное и максимальное значения для этого запуска симуляции. Последующие запуски накапливают результаты инструментирования, пока они не будут удалены с помощью 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;
Результаты инструментирования накапливаются до тех пор, пока они не будут очищены с помощью 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);
Создайте инструментальную 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>