定点设计师快速入门
- 定点设计师产品说明
- 系统要求
教程
MATLAB工作流
在MATLAB中创建定点数据
定点基础知识
执行定点算术
“执行定点算术”
查看定点数据
示例代码中使用的fi
对象显示设置
加速定点仿真
此示例说明如何使用fiaccel
函数来加速定点算法。您可以从MATLAB®代码生成MEX函数,运行生成的MEX函数,并使用MATLAB代码仿真比较执行速度。
使用Min / Max Instrumentation设置数据类型
此示例显示如何通过检测最小/最大日志记录的MATLAB代码并使用工具建议数据类型来设置定点数据类型。
生成定点C代码
生成独立的定点C代码
手动将浮点MATLAB算法转换为定点
手动将浮点MATLAB算法转换为定点
Simulink工作流
开发和测试定点系统
模拟动态系统的开发周期概述
在Simulink模型和MATLAB之间传递定点数据
阅读从MATLAB定点数据®到您的Simulink ®模型,从模型和模拟登录定点信息到工作区。
配置具有定点输出的块
通过配置Simulink模块输出定点信号来创建定点模型。
从双打到固定点
提供基于该fxpdemo_dbl2fix
模型的示例,该示例突出了Fixed-Point Designer™软件的许多关键功能
将浮点模型转换为不动点
详细说明将浮点模型转换为固定点所采取的步骤。
共享定点模型
使用数据类型覆盖设置来共享和编辑包含定点块的模型,而无需使用定点设计器软件。
关于定点
- 使用定点硬件的好处
- 定点数据类型
定点数据类型
- 精度和范围
讨论定点设计器中算术运算背后的概念
- 缩放
讨论定点设计器中使用的缩放类型; 二进制仅点和[斜率偏差]
- 算术运算
介绍定点设计器中算术运算背后的概念
- 物理量和测量量表
提供测量标度和代表数字的概述
- 词汇表
- 精选参考书目
Fixed-Point Designer 产品说明
Fixed-Point Designer™ 提供开发定点和单精度算法所需的数据类型和工具,以在嵌入式硬件上进行性能优化。Fixed-Point Designer 会分析您的设计并提供建议的数据类型和属性,例如字长和定标。您可以指定详细的数据属性,如舍入模式和溢出操作,以及混合单精度和定点数据。您可以执行位真仿真来观察有限范围和精度的影响,而无需在硬件上实现设计。
Fixed-Point Designer 可让您将双精度算法转换为单精度或定点。您可以创建和优化满足数值精度要求和目标硬件约束的数据类型。您可以通过数学分析或检测后的仿真来确定设计的范围要求。Fixed-Point Designer 提供的 App 和工具可指导您完成数据转换过程,并允许您将定点结果与浮点基线进行比较。
Fixed-Point Designer 支持 C、HDL 和 PLC 代码生成。
主要功能
-
MATLAB®、Simulink® 和 Stateflow® 中的定点数据类型设定
-
定点和单精度算法的位真仿真
-
用于探查和优化数据类型的直方图和相关工具
-
用于从双精度转换为定点或单精度的 App
-
用于收集仿真最小值和最大值的检测
-
用于评估完整设计最小值和最大值的范围分析
-
用于调试和可视化的溢出检测和精度丢失工具
教程:MATLAB工作流
在 MATLAB 中创建定点数据
以下示例说明如何使用 Fixed-Point Designer™ fi
对象创建定点数据。
对数字调用 fi
会生成具有默认符号性、默认字长和小数长度的定点数。
fi(pi)
ans = 3.1416 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 13
您可以指定符号性(1 表示有符号,0 表示无符号)以及字长和小数长度。
fi(pi,1,15,12)
ans = 3.1416 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 15 FractionLength: 12
fi
和 numerictype
对象
要创建定点整数值,请指定小数长度为 0。
fi(1:25,0,8,0)
ans = Columns 1 through 13 1 2 3 4 5 6 7 8 9 10 11 12 13 Columns 14 through 25 14 15 16 17 18 19 20 21 22 23 24 25 DataTypeMode: Fixed-point: binary point scaling Signedness: Unsigned WordLength: 8 FractionLength: 0
fi(rand(4),0,12,8)
ans = 0.1484 0.8125 0.1953 0.3516 0.2578 0.2422 0.2500 0.8320 0.8398 0.9297 0.6172 0.5859 0.2539 0.3516 0.4727 0.5508 DataTypeMode: Fixed-point: binary point scaling Signedness: Unsigned WordLength: 12 FractionLength: 8
编写代码时,您有时需要为变量测试不同数据类型。将变量的数据类型与算法分离使测试变得更加简单。通过创建数据类型定义表,您可以编程方式使函数在浮点数据类型和定点数据类型之间切换。以下示例说明如何使用此方法和创建由零组成的数组。
T.z = fi([],1,16,0); z = zeros(2,3,'like',T.z)
z = 0 0 0 0 0 0 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 0
注意
有关说明此方法的实现的完整示例,请参阅Implement FIR Filter Algorithm for Floating-Point and Fixed-Point Types using cast and zeros。
定点算术
加减法
将两个定点数相加时,您可能需要一个进位位来正确表示结果。因此,将两个B位数(具有相同的定标)相加时,与使用两个操作数时相比,结果值有一个额外的位。
a = fi(0.234375,0,4,6); c = a + a
c = 0.4688 DataTypeMode:定点:二进制点缩放 签名:未签名 WordLength:5 分数长度:6
a.bin
ans = 1111
c.bin
ans = 11110
。如果对具有不同精度的两个数字执行加法或减法,首先需要对齐小数点才能执行运算结果是:运算结果与操作数之间存在多于一位的差异。
a = fi(pi,1,16,13); b = fi(0.1,1,12,14); c = a + b
c = 3.2416 DataTypeMode:定点:二进制点缩放 签名:签名 WordLength:18 分数长度:14
乘法
通常,全精度乘积需要的字长等于各操作数字长之和。在以下示例中,请注意,乘积c
的字长等于a
的字长加上b
的字长。c
的小数长度也。等于a
的小数长度加上b
的小数长度。
a = fi(pi,1,20),b = fi(exp(1),1,16)
a = 3.1416 DataTypeMode:定点:二进制点缩放 签名:签名 WordLength:20 分数长度:17 b = 2.7183 DataTypeMode:定点:二进制点缩放 签名:签名 WordLength:16 分数长度:13
c = a * b
c = 8.5397 DataTypeMode:定点:二进制点缩放 签名:签名 WordLength:36 分数长度:30
与其他内置数据类型的数学运算
注意,在Ç语言中,整数数据类型和双精度数据类型之间的运算结果会提升为双精度类型。但是,在MATLAB ®中,内置的整数数据类型和双精度数据类型之间的运算结果是整数。在这方面,fi
对象的行为与MATLAB中的内置整数数据类型相似。
在fi
状语从句:double
之间进行加法运算时,双精度会转换为与原fi
输入侧具有相同数值类型的fi
。该运算的结果是fi
。在当fi
状语从句:double
之间进行乘法运算时,双精度会转换为fi
,其字长和符号与性原fi
相同御姐具有最佳精度的小数长度。该运算的结果是fi
。
a = fi(pi);
a = 3.1416 DataTypeMode:定点:二进制点缩放 签名:签名 WordLength:16 分数长度:13
b = 0.5 * a
b = 1.5708 DataTypeMode:定点:二进制点缩放 签名:签名 WordLength:32 分数长度:28
内置在整数数据类型[u]int[8, 16, 32]
之一与fi
之间进行算术运算时,保留整数的字长和符号性。该运算的结果是fi
。
a = fi(pi); b = int8(2)* a
b = 6.2832 DataTypeMode:定点:二进制点缩放 签名:签名 WordLength:24 分数长度:13
在fi
与逻辑数据类型之间进行算术运算时,逻辑值被视为值为0或1且字长为1的无符号fi
对象。该运算的结果是fi
对象。
a = fi(pi); b =逻辑(1); c = a * b
c = 3.1416 DataTypeMode:定点:二进制点缩放 签名:签名 WordLength:17 分数长度:13
fimath对象
fimath
属性定义对fi
对象执行算术运算的规则,包括数学,舍入和溢出属性。fi
对象可以有局部fimath
对象,它也。可以使用默认fimath
属性。您可以使用setfimath
将fimath
对象附加到fi
对象。您也。可以在创建³³时在fi
构造函数指定中fimath
属性。当fi
对象具有局部fimath
而不是使用默认属性时,fi
对象的显示中将显示fimath
属性。在此示例中,a
具有在构造函数中指定的ProductMode
属性。
a = fi(5,1,16,4,'ProductMode','KeepMSB')
a = 五 DataTypeMode:定点:二进制点缩放 签名:签名 WordLength:16 分数长度:4 RoundingMethod:最近的 溢出动作:饱和 ProductMode:KeepMSB ProductWordLength:32 SumMode:FullPrecision
a
的ProductMode
属性设置为KeepMSB
,其余而的fimath
属性使用默认值。
注意
有关fimath
对象及其属性和默认值的详细信息,请参阅fimath对象属性。
位增长
表下显示fi
对象A
状语从句:B
的SumMode
状语从句:ProductMode
属性使用默认fimath
值FullPrecision
时的位增长。
一个 | 乙 | Sum = A + B. | 产品= A * B. | |
---|---|---|---|---|
格式 | fi(vA,s1,w1,f1) |
fi(vB,s2,w2,f2) |
- | - |
符号 | s1 |
s2 |
Ssum =(|| )s1 s2 |
Sproduct =(|| )s1 s2 |
整数位 | I1 = w1-f1-s1 |
I2= w2-f2-s2 |
Isum = max(w1-f1, w2-f2) + 1 - Ssum |
Iproduct = (w1 + w2) - (f1 + f2) |
小数位 | f1 |
f2 |
Fsum = max(f1, f2) |
Fproduct = f1 + f2 |
总位数 | w1 |
w2 |
Ssum + Isum + Fsum |
w1 + w2 |
示例此说明在for
循环中发生的位增长。
T.acc = fi([],1,32,0); Tx = fi([],1,16,0); x = cast(1:3,'like',Tx); acc = zeros(1,1,'like',T.acc); 对于 n = 1:长度(x) acc = acc + x(n) 结束
acc = 1 s33,0 acc = 3 s34,0 acc = 6 s35,0
acc
的字长也随之增加这种增加会导致两个问题:。一个是代码生成不允许在循环中更改数据类型另一个是,如果循环足够长,则会在MATLAB中耗尽内存。请参阅控制位增长了解避免此问题的一些策略。
控制位增长
使用fimath
指定通过fi
对象的fimath
属性,您可以控制在对对象执行运算时的位增长。
F = fimath('SumMode','SpecifyPrecision','SumWordLength',8,...... 'SumFractionLength',0); a = fi(8,1,8,0,F); b = fi(3,1,8,0); c = a + b
c = 11 DataTypeMode:定点:二进制点缩放 签名:签名 WordLength:8 分数长度:0 RoundingMethod:最近的 溢出动作:饱和 ProductMode:FullPrecision SumMode:SpecifyPrecision SumWordLength:8 SumFractionLength:0 CastBeforeSum:是的
fi
对象a
具有局部fimath
对象F
。F
指定和的字长和小数长度。在默认fimath
设置下,输出c
通常字长为9,小数长度为0.但是,由于a
具有局部fimath
对象,因此生成的fi
对象的字长为8,小数长度为0。
还您可以使用fimath
属性来控制for
循环中的位增长。
F = fimath('SumMode','SpecifyPrecision','SumWordLength',32,...... 'SumFractionLength',0); T.acc = fi([],1,32,0,F); Tx = fi([],1,16,0); x = cast(1:3,'like',Tx); acc = zeros(1,1,'like',T.acc); 对于 n = 1:长度(x) acc = acc + x(n) 结束
acc = 1 s32,0 acc = 3 s32,0 acc = 6 s32,0
与T.acc
使用默认fimath
属性时不同,acc
的位增长现在受到限制。因此,acc
的字长保持为32。
下标赋值
控制位增长的另一种方法是使用下标赋值。a(I) = b
将b
的值赋给由下标向量I
指定的a
的元素,保留同时a
的numerictype
。
T.acc = fi([],1,32,0); Tx = fi([],1,16,0); x = cast(1:3,'like',Tx); acc = zeros(1,1,'like',T.acc); %分配到ACC而不改变其类型 为 n = 1时:长度(X) acc(:) = acc + x(n) 结束
acc(:) = acc + x(n)指示下标向量(:)
处的值发生更改。但是,输出acc
的numerictype
保持不变。由于acc
是标量,因此如果您使用(1)
作为下标向量,则也会收到相同的输出。
对于 n = 1:numel(x) acc(1)= acc + x(n); 结束
acc = 1 s32,0 acc = 3 s32,0 acc = 6 s32,0
acc
的numerictype
在for
循环的每次迭代中保持不变。
下标赋值还可以帮助您控制函数中的位增长。在函数cumulative_sum
中,y
的numerictype
不会更改,但由n指定的元素中的值会更改。
function y = cumulative_sum(x) %CUMULATIVE_SUM向量元素的累积和。 % 对于向量,Y = cumulative_sum(X)是包含 X元素的累积和的百分比的向量.Y的类型是X的类型 .y =零(size(x),'like',x) ; y(1)= x(1); 对于 n = 2:长度(x) y(n)= y(n-1)+ x(n); 年底 结束
y = cumulative_sum(fi([1:10],1,8,0))
y = 1 3 6 10 15 21 28 36 45 55 DataTypeMode:定点:二进制点缩放 签名:签名 WordLength:8 分数长度:0
注意
有关下标赋值的详细信息,参阅请subsasgn
函数。
accumpo和accumneg
位控制的增长另一种方法的英文使用accumpos
状语从句:accumneg
函数来执行加法减法状语从句:运算。与使用下标赋值类似,accumpos
状语从句:accumneg
保留其输入侧fi
对象之一的数据类型,同时允许您指定舍入方法和输入值中的溢出操作。
有关如何实现accumpos
和accumneg
的详细信息,请参阅避免生成代码中的多字操作
溢出和舍入
在执行定点算术时,考虑溢出的可能性和后果。fimath
对象指定执行算术运算时使用的溢出和舍入模式。
溢出
当运算结果超过最大或最小可表示值时,可能会发生溢出。fimath
对象具有OverflowAction
属性,它提供两种处理溢出的方法:与饱和回绕如果将OverflowAction
设置为saturate
,则溢出会通过饱和方式限制为该范围内的最大值或最小值。如果将OverflowAction
设置为wrap
,则任何溢出都将绕回,对于无符号值,会采用模运算绕回,对于有符号值,则采用2的补码绕回。
有关如何检测溢出的详细信息,请参阅使用fipref进行下溢和溢出记录。
舍入
选择舍入方法时需要考虑几个因素,包括成本,偏置以及是否存在溢出的可能性.Fixed-Point Designer™软件提供了几个不同舍入函数来满足您的设计要求。
舍入方法 | 说明 | 成本 | 偏差 | 是否可能溢出 |
---|---|---|---|---|
ceil |
舍入到正无穷大方向最接近的可表示数字。 | 低 | 大的正向偏差 | 是 |
convergent |
舍入到最接近的可表示数字。在舍入机会均等的情况下,convergent 舍入到最接近的偶数。这种方法是由工具箱提供的最小偏置舍入方法。 |
高 | 无偏差 | 是 |
floor |
舍入到负无穷大方向上最接近的可表示数字,相当于2的补码截断。 | 低 | 大的负向偏差 | 否 |
nearest |
舍入到最接近的可表示数字。在舍入机会均等的情况下,nearest 在正无穷大的方向上舍入到最接近的可表示数字。舍此入方法的英文fi 对象创建³³状语从句:fi 算术的默认值。 |
中等 | 小的正向偏差 | 是 |
round |
。舍入到最接近的可表示数字在舍入机会均等的情况下,round 方法进行如下舍入:
|
高 |
|
是 |
fix |
舍入到零方向上最接近的可表示数字。 | 低 |
|
否 |
查看定点数据
在 Fixed-Point Designer™ 软件中,fipref
对象确定 fi
对象的显示属性。对于 fi
对象,代码示例通常在它们与下列 fipref
对象属性一起使用时才显示它们:
-
NumberDisplay
-'RealWorldValue'
-
NumericTypeDisplay
-'full'
-
FimathDisplay
-'full'
通过将 'FimathDisplay'
设置为 'full'
,可以快速、轻松地区分具有局部 fimath 配置的 fi
对象和那些与默认 fimath 配置相关联的对象。当 'FimathDisplay'
设置为 'full'
时,MATLAB® 显示具有局部 fimath 配置的 fi
对象的 fimath
对象属性。MATLAB 不会显示与默认 fimath 配置相关联的 fi
对象的 fimath
对象属性。由于存在这种显示差异,您只需通过查看输出即可知道 fi
对象是否与默认 fimath 配置相关联。
此外,除非另有说明,否则整个 Fixed-Point Designer 文档中的示例都使用 fimath 的以下默认配置:
RoundingMethod: Nearest OverflowAction: Saturate ProductMode: FullPrecision SumMode: FullPrecision
有关显示设置的详细信息,请参阅fi Object Display Preferences Using fipref。
显示 fi 对象的 fimath 属性
要查看大多数 Fixed-Point Designer 代码示例中显示的输出,请按如下所示设置 fipref
属性并创建两个 fi
对象:
p = fipref('NumberDisplay', 'RealWorldValue',... 'NumericTypeDisplay', 'full', 'FimathDisplay', 'full'); a = fi(pi,'RoundingMethod', 'Floor', 'OverflowAction', 'Wrap') b = fi(pi)
MATLAB 返回以下内容:
a = 3.1415 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 13 RoundingMethod: Floor OverflowAction: Wrap ProductMode: FullPrecision SumMode: FullPrecision b = 3.1416 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 13
MATLAB 在 fi
对象 a
的输出中显示 fimath
对象属性,因为 a
具有局部 fimath 配置。
MATLAB 在 fi
对象 b
的输出中不显示任何 fimath
对象属性,因为 b
将自身与默认 fimath 关联。
隐藏 fi 对象的 fimath 属性
如果您正在使用多个具有局部 fimath 配置的 fi
对象,则可能需要关闭 fimath
对象显示:
-
NumberDisplay
-'RealWorldValue'
-
NumericTypeDisplay
-'full'
-
FimathDisplay
-'none'
例如,
p = fipref('NumberDisplay','RealWorldValue',... 'NumericTypeDisplay','full','FimathDisplay','none') p = NumberDisplay: 'RealWorldValue' NumericTypeDisplay: 'full' FimathDisplay: 'none' LoggingMode: 'Off' DataTypeOverride: 'ForceOff' F = fimath('RoundingMethod','Floor','OverflowAction','Wrap'); a = fi(pi, F) a = 3.1415 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 13
尽管此设置有助于减少产生的输出量,但它也导致无法根据输出判断 fi
对象是否使用默认 fimath。为此,您可以使用 isfimathlocal
函数。例如,
isfimathlocal(a) ans = 1
当 isfimathlocal
函数返回 1
时,fi
对象具有局部 fimath 配置。如果函数返回 0
,则 fi
对象使用默认 fimath 配置。
缩短 fi 对象的数值类型显示
要进一步减少输出量,可以将 NumericTypeDisplay
设置为 'short'
。例如,
p = fipref('NumberDisplay','RealWorldValue',... 'NumericTypeDisplay','short','FimathDisplay','full'); a = fi(pi) a = 3.1416 s16,13
加速定点仿真
此示例说明如何使用 fiaccel
函数来加速定点算法。您可以从 MATLAB® 代码生成 MEX 函数,运行生成的 MEX 函数,并使用 MATLAB 代码仿真比较执行速度。
示例说明
此示例使用一阶反馈回路。它还使用量化器来避免无限的位增长。输出信号被延迟一个采样周期并通过回馈来缓冲输入信号。
复制必需的文件
您需要此 MATLAB 文件来运行此示例。将其复制到临时目录。此步骤需要具有对系统临时目录的写入访问权限。
tempdirObj = fidemo.fiTempdir('fiaccelbasicsdemo'); fiacceldir = tempdirObj.tempDir; fiaccelsrc = ... fullfile(matlabroot,'toolbox','fixedpoint','fidemos','+fidemo','fiaccelFeedback.m'); copyfile(fiaccelsrc,fiacceldir,'f');
检查 MATLAB 反馈函数代码
执行反馈回路的 MATLAB 函数位于文件 fiaccelFeedback.m
中。以下代码将量化输入,并执行反馈回路操作:
type(fullfile(fiacceldir,'fiaccelFeedback.m'))
function [y,w] = fiaccelFeedback(x,a,y,w) %FIACCELFEEDBACK Quantizer and feedback loop used in FIACCELBASICSDEMO. % Copyright 1984-2013 The MathWorks, Inc. %#codegen for n = 1:length(x) y(n) = quantize(x(n) - a*w, true, 16, 12, 'floor', 'wrap'); w = y(n); end
此函数中使用以下变量:
-
x
是输入信号向量。 -
y
是输出信号向量。 -
a
是反馈增益。 -
w
是延迟一个单位时间的输出信号。
创建输入信号并初始化变量
rng('default'); % Random number generator x = fi(2*rand(1000,1)-1,true,16,15); % Input signal a = fi(.9,true,16,15); % Feedback gain y = fi(zeros(size(x)),true,16,12); % Initialize output. Fraction length % is chosen to prevent overflow w = fi(0,true,16,12); % Initialize delayed output A = coder.Constant(a); % Declare "a" constant for code % generation
运行 Normal 模式
tic, y = fiaccelFeedback(x,a,y,w); t1 = toc;
编译反馈代码的 MEX 版本
fiaccel fiaccelFeedback -args {x,A,y,w} -o fiaccelFeedback_mex
运行 MEX 版本
tic y2 = fiaccelFeedback_mex(x,y,w); t2 = toc;
加速比
代码加速为通过 MEX 文件生成加速定点算法提供优化。Fixed-Point Designer™ 提供了一个方便的函数 fiaccel
来将您的 MATLAB 代码转换为 MEX 函数,这可以大大加快定点算法的执行速度。
r = t1/t2
r = 12.7097
清理临时文件
clear fiaccelFeedback_mex; tempdirObj.cleanUp;
使用Min / Max Instrumentation设置数据类型
此示例显示如何通过检测用于最小/最大日志记录的MATLAB®代码并使用工具建议数据类型来设置定点数据类型。
您将使用的功能是:
-
buildInstrumentedMex
- 在启用检测的情况下构建MEX功能 -
showInstrumentationResults
- 显示检测结果 -
clearInstrumentationResults
- 清除仪器结果
被测单位
在此示例中转换为定点的函数是二阶直接形式2转置过滤器。您可以用自己的功能代替这个功能,在您自己的工作中重现这些步骤。
函数 [Y,Z] = fi_2nd_order_df2t_filter(B,A,X,Y,Z) 为 I = 1:长度(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); 年底 结束
对于要检测的MATLAB®函数,它必须适合代码生成。有关代码生成的信息,请参阅参考页面buildInstrumentedMex
。不需要使用MATLAB®Coder™许可证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); 复位(fipref)
数据类型由设计要求决定
在此示例中,设计要求确定输入的数据类型x
。这些要求是有符号的,16位和小数。
N = 256; x = fi(零(N,1),1,16,15);
设计要求还决定了具有40位累加器的DSP目标的定点数学运算。此示例使用地板舍入和换行溢出来生成高效的生成代码。
F = fimath('RoundingMethod','Floor',...... 'OverflowAction','Wrap',...... 'ProductMode','KeepLSB',...... 'ProductWordLength',40,...... 'SumMode','KeepLSB',...... 'SumWordLength',40);
以下系数对应于由2创建的二阶低通滤波器
[num,den] =黄油(2,0.125)
系数的值会影响将分配给滤波器输出和状态的值的范围。
num = [0.0299545822080925 0.0599091644161849 0.0299545822080925]; den = [1 -1.4542435862515900 0.5740619150839550];
由设计要求确定的系数的数据类型被指定为16位字长并且被缩放到最佳精度。fi
从常系数创建对象的模式是:
1. fi
使用默认的舍入到最近和饱和溢出设置将系数投射到对象,这使得系数更精确。
2.附加fimath
地板舍入和包装溢出设置以控制算术,从而产生更高效的C代码。
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
。使用缩放的双数据类型创建它们,以便它们的值达到全范围,您可以识别潜在的溢出并建议数据类型。
yisd = fi(零(N,1),1,16,15,'DataType','ScaledDouble','fimath',F); zisd = fi(零(2,1),1,16,15,'DataType','ScaledDouble','fimath',F);
将MATLAB®功能用作缩放双MEX功能
要检测MATLAB®代码,可以使用buildInstrumentedMex
命令从MATLAB®函数创建MEX函数。输入与输入buildInstrumentedMex
相同fiaccel
,但buildInstrumentedMex
没有对象fi
限制。输出buildInstrumentedMex
是带有仪器插入的MEX功能,因此在运行MEX功能时,将记录所有命名变量和中间值的模拟最小值和最大值。
使用该'-o'
选项命名生成的MEX函数。如果不使用该'-o'
选项,则MEX函数是'_mex'
附加的MATLAB®函数的名称。您也可以将MEX功能命名为与MATLAB®功能相同,但您需要记住MEX功能优先于MATLAB®功能,因此在重新生成MEX功能之前,MATLAB®功能的更改不会运行,或者删除并清除MEX功能。
buildInstrumentedMex fi_2nd_order_df2t_filter ...
-o filter_scaled_double ...
-args {B,A,X,yisd,zisd}
带有啁啾输入的测试台
该系统的测试台设置为运行啁啾和步进信号。通常,系统的测试台应覆盖各种输入信号。
第一个测试平台使用啁啾输入。啁啾信号是很好的代表性输入,因为它涵盖了很宽的频率范围。
t = linspace(0,1,N); %时间矢量从0到1秒 f1 = N / 2; %啁啾的目标频率设置为Nyquist xchirp = sin(pi * f1 * t。^ 2); %线性啁啾从0到Fs / 2 Hz,1秒 x(:) = xchirp; %将啁啾投射到定点
运行Instrumented MEX功能以记录最小值/最大值
必须运行检测的MEX功能以记录该模拟运行的最小值和最大值。后续运行会累积检测结果,直到清除它们为止clearInstrumentationResults
。
请注意,分子和分母系数被编译为常量,因此它们不作为生成的MEX函数的输入提供。
ychirp = filter_scaled_double(x,yisd,zisd);
滤波的线性调频信号的曲线图示出了具有这些特定系数的滤波器的低通行为。低频通过,较高频率衰减。
CLF 情节(t,x,'c',t,ychirp,'bo-') 标题('唧唧') 图例('输入','缩放双输出') 图(GCF); 的DrawNow;
显示Chirp的建议分数长度的仪器结果
该showInstrumentationResults
命令显示带有检测值的代码生成报告。输入to showInstrumentationResults
是您希望显示结果的已检测MEX函数的名称。
这是showInstrumentationResults
命令的选项列表:
-
-defaultDT T
建议用于双精度的默认数据类型,其中T
是numerictype
对象或其中一个字符串{remainFloat, double, single, int8, int16, int32, int64, uint8, uint16, uint32, uint64}
。默认是remainFloat
。 -
-nocode
不要在可打印报告中显示MATLAB代码。仅显示已记录的变量表。此选项仅与-printable选项结合使用。 -
-optimizeWholeNumbers
优化变量的字长,其模拟最小/最大日志表明它们始终是整数。 -
-percentSafetyMargin N
模拟最小值/最大值的安全裕度,其中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;
使用步进输入运行Instrumented MEX功能
仪器结果将被累积,直到它们被清除clearInstrumentationResults
。
ystep = filter_scaled_double(x,yisd,zisd); CLF 情节(t,x,'c',t,ystep,'bo-') 标题('步骤') 图例('输入','缩放双输出') 图(GCF); 的DrawNow;
显示累计仪器结果
即使步进和啁啾输入的输入都是全范围,如x
仪表代码生成报告中的100%电流范围所示,步进输入也会导致溢出,而啁啾输入则不会。这说明了为测试平台提供许多不同输入的必要性。出于本示例的目的,仅使用了两个输入,但真正的测试平台应该更彻底。
showInstrumentationResults filter_scaled_double -proposeFL
应用建议的定点属性
为了防止基于的14位用于所提出的分数长度溢出,建议设置定点特性y
和z
从所述仪表化代码生成报告。
在工作流程的这一点上,您使用了真正的定点类型(而不是在确定数据类型的早期步骤中使用的缩放双重类型)。
yi = fi(零(N,1),1,16,14,'fimath',F); zi = fi(零(2,1),1,16,14,'fimath',F);
将MATLAB®功能用作定点MEX功能
使用定点输入和buildInstrumentedMex
命令创建仪表化定点MEX功能。
buildInstrumentedMex fi_2nd_order_df2t_filter ...
-o filter_fixed_point ...
-args {B,A,x,yi,zi}
验证定点算法
转换到定点后,再次使用定点输入运行测试台以验证设计。
使用Chirp输入验证
使用啁啾输入运行定点算法以验证设计。
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('幅度') 图例('输入','缩放双输出','定点输出'); 标题('定点啁啾') subplot(212); plot(t,err,'r'); title('Error'); xlabel('t'); ylabel('err'); 图(GCF); 的DrawNow;
检查变量和中间结果,以确保最小/最大值在范围内。
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') 标题('定点步骤'); 图例('输入','缩放双输出','定点输出') subplot(212); plot(t,err,'r'); title('Error'); xlabel('t'); ylabel('err'); 图(GCF); 的DrawNow;
检查变量和中间结果,以确保最小/最大值在范围内。
showInstrumentationResults filter_fixed_point
运行以下代码以还原全局状态。
fipref(FIPREF_STATE); clearInstrumentationResults filter_fixed_point clearInstrumentationResults filter_scaled_double 明确fi_2nd_order_df2t_filter_fixed_instrumented 明确fi_2nd_order_df2t_filter_float_instrumented
运行以下代码以删除临时目录。
tempdirObj.cleanUp; %#确定<* ASGLU>
生成定点 C 代码
注意
要从 MATLAB® 生成定点代码,您必须同时拥有 Fixed-Point Designer™ 产品和 MATLAB Coder™ 产品。您还必须有 C 编译器。
此示例说明如何为简单的函数生成代码,该函数将两个输入值相乘并累加。这是可以嵌入在外部硬件中的代码的类型。函数是
function acc = mult_acc(x,a,acc) acc = accumpos(acc,x*a);
以下代码定义测试平台输入,设置必需的代码生成属性并生成代码。测试平台输入被指定为定点数。x
输入为随机数,a
为 0.9,累加器 acc
初始化为 0。coder.HardwareImplementation
对象指定影响生成代码的外部硬件的属性。这些示例指定一个 40 位累加器。coder.CodeConfig
对象具有直接影响代码生成的属性。codegen
命令将函数、配置对象作为输入参数并生成可嵌入的 C 代码。
x = fi(rand,true,16,15); a = fi(0.9,true,16,15); acc = fi(0,true,40,30); %% hi = coder.HardwareImplementation; hi. ProdHWDeviceType = 'Generic->Custom' hi. TargetHWDeviceType = 'Generic->Custom' hi.TargetBitPerLong = 40; hi.ProdBitPerLong = 40; hc = coder.config('lib'); hc.HardwareImplementation = hi; hc.GenerateReport = true; codegen mult_acc -config hc -args {x,a,acc}
生成的 C 代码是
/* * mult_acc.c * * Code generation for function 'mult_acc' */ /* Include files */ #include "rt_nonfinite.h" #include "mult_acc.h" /* Function Definitions */ void mult_acc(short x, short a, long *acc) { *acc += x * a; } /* End of code generation (mult_acc.c) */
注意
有关支持代码生成的函数的列表,请参阅Functions and Objects Supported for C/C++ Code Generation — Alphabetical List。
手动将浮点 MATLAB 算法转换为定点
此示例说明如何将浮点算法转换为定点,然后为该算法生成 C 代码。该示例使用以下最佳做法:
-
将算法与测试文件分离。
-
为检测和代码生成准备算法。
-
管理数据类型并控制位增长。
-
通过创建数据定义表将数据类型定义与算法代码分离。
有关最佳做法的完整列表,请参阅Manual Fixed-Point Conversion Best Practices。
将算法与测试文件分离
编写 MATLAB® 函数 mysum
,它对向量的元素求和。
function y = mysum(x) y = 0; for n = 1:length(x) y = y + x(n); end end
由于您只需要将算法部分转换为定点,因此编写代码时,将执行核心处理的算法与测试文件分离,可提升效率。
编写测试脚本
在测试文件中,创建您的输入、调用算法并绘制结果。
-
编写 MATLAB 脚本
mysum_test
,它使用双精度数据类型验证您的算法的行为。n = 10; rng default x = 2*rand(n,1)-1; % Algorithm y = mysum(x); % Verify results y_expected = sum(double(x)); err = double(y) - y_expected
rng default
使 rand 函数使用的随机数生成函数的设置采用其默认值,以便它生成的随机数与重新启动 MATLAB 后生成的随机数相同。 -
运行测试脚本。
mysum_test
err = 0
使用
mysum
获得的结果与使用 MATLABsum
函数获得的结果相匹配。
有关详细信息,请参阅Create a Test File。
为检测和代码生成准备算法
在您的算法中,在函数签名后,添加 %#codegen
编译指令以指示您要将算法用于检测并为其生成 C 代码。添加此指令将指示 MATLAB 代码分析器帮助您诊断并修复在检测和代码生成过程中会导致错误的违规情况。
function y = mysum(x) %#codegen y = 0; for n = 1:length(x) y = y + x(n); end end
对于此算法,编辑器窗口右上角的代码分析器指示标记保持绿色,告诉您它没有检测到任何问题。
有关详细信息,请参阅Prepare Your Algorithm for Code Acceleration or Code Generation。
为原始算法生成 C 代码
为原始算法生成 C 代码以验证该算法适用于代码生成并查看浮点 C 代码。使用 codegen
函数(需要 MATLAB Coder™)来生成 C 库。
-
将以下行添加到测试脚本的末尾,为
mysum
生成 C 代码。codegen mysum -args {x} -config:lib -report
-
再次运行测试脚本。
MATLAB Coder 为
mysum
函数生成 C 代码,并提供代码生成报告的链接。 -
点击该链接以打开代码生成报告并查看为
mysum
生成的 C 代码。/* Function Definitions */ double mysum(const double x[10]) { double y; int n; y = 0.0; for (n = 0; n < 10; n++) { y += x[n]; } return y; }
由于 C 不允许浮点索引,因此循环计数器
n
会自动声明为整数类型。您不需要将n
转换为定点。输入
x
和输出y
声明为双精度类型。
管理数据类型和控制位增长
用单精度类型测试您的算法以检查类型是否匹配
-
修改您的测试文件,以使
x
的数据类型为单精度。n = 10; rng default x = single(2*rand(n,1)-1); % Algorithm y = mysum(x); % Verify results y_expected = sum(double(x)); err = double(y) - y_expected codegen mysum -args {x} -config:lib -report
-
再次运行测试脚本。
mysum_test
err = -4.4703e-08 ??? This assignment writes a 'single' value into a 'double' type. Code generation does not support changing types through assignment. Check preceding assignments or input type specifications for type mismatches.
代码生成失败,报告
y = y + x(n);
行中的数据类型不匹配。 -
要查看错误,请打开报告。
在报告中,在
y = y + x(n)
行上,报告以红色突出显示赋值的左侧的y
,表明存在错误。存在的问题是:y
声明为双精度类型,但被赋予一个单精度类型值。y + x(n)
是双精度和单精度值之和,该和为单精度值。如果将光标置于报告中的变量和表达式上,可以看到有关它们的类型的信息。在此处,您可以看到表达式y + x(n)
是单精度类型。 -
要修复类型不匹配,请更新您的算法以对元素之和使用下标赋值。将
y = y + x(n)
更改为y(:) = y + x(n)
。function y = mysum(x) %#codegen y = 0; for n = 1:length(x) y(:) = y + x(n); end end
使用下标赋值时,您还可以防止位增长,位增长是添加定点数时的默认行为。有关详细信息,请参阅位增长。防止位增长非常重要,因为您要在整个代码中保持定点类型。有关详细信息,请参阅控制位增长。
-
重新生成 C 代码并打开代码生成报告。在 C 代码中,结果现在转换为双精度类型来解决类型不匹配问题。
编译检测后的 MEX
使用 buildInstrumentedMex
函数来检测算法,以记录所有命名变量和中间变量的最小值和最大值。使用 showInstrumentationResults
函数根据这些记录的值建议定点数据类型。稍后,您将使用这些建议的定点类型来测试您的算法。
-
更新测试脚本:
-
声明
n
后,添加buildInstrumentedMex mySum —args {zeros(n,1)} -histogram
。 -
将
x
更改为双精度类型。用x = 2*rand(n,1)-1;
替换x = single(2*rand(n,1)-1);
-
调用生成的 MEX 函数,而不是调用原始算法。将
y = mysum(x)
更改为y=mysum_mex(x)
。 -
调用 MEX 函数后,添加
showInstrumentationResults mysum_mex -defaultDT numerictype(1,16) -proposeFL
。-defaultDT numerictype(1,16) -proposeFL
标志表示您要为 16 位字长度建议小数长度。这是更新后的测试脚本。
%% Build instrumented mex n = 10; buildInstrumentedMex mysum -args {zeros(n,1)} -histogram %% Test inputs rng default x = 2*rand(n,1)-1; % Algorithm y = mysum_mex(x); % Verify results showInstrumentationResults mysum_mex ... -defaultDT numerictype(1,16) -proposeFL y_expected = sum(double(x)); err = double(y) - y_expected %% Generate C code codegen mysum -args {x} -config:lib -report
-
-
再次运行测试脚本。
showInstrumentationResults
函数建议数据类型并打开报告以显示结果。 -
在报告中,点击 Variables 选项卡。
showInstrumentationResults
对y
建议小数长度为 13,对x
建议小数长度为 15。
在报告中,您可以:
-
查看输入
x
和输出y
的仿真最小值和最大值。 -
查看对
x
和y
建议的数据类型。 -
查看代码中所有变量、中间结果和表达式的信息。
要查看此信息,请将光标放在报告中的变量或表达式上。
-
查看
x
和y
的直方图数据,以帮助您根据当前数据类型识别超出范围或低于精度的任何值。要查看特定变量的直方图,请点击其直方图图标 。
将数据类型定义与算法代码分离
不要手动修改算法来检查每种数据类型的行为,而是将数据类型定义与算法分离。
修改 mysum
使其使用输入参数 T
,它是一种用于定义输入和输出数据的数据类型的结构体。当首先定义 y
时,使用 cast
函数的类似于 cast(x,'like',y)
的语法将 x
转换为所需的数据类型。
function y = mysum(x,T) %#codegen y = cast(0,'like',T.y); for n = 1:length(x) y(:) = y + x(n); end end
创建数据类型定义表
编写函数 mytypes
,它定义您要用于测试算法的不同数据类型。在您的数据类型表中,包括双精度、单精度和定标双精度数据类型以及前面建议的定点数据类型。在将算法转换为定点之前,最好做法是:
-
使用双精度值测试数据类型定义表和算法之间的关联。
-
使用单精度值测试算法来查找数据类型不匹配和其他问题。
-
使用定标双精度值运行算法来检查是否存在溢出。
function T = mytypes(dt) switch dt case 'double' T.x = double([]); T.y = double([]); case 'single' T.x = single([]); T.y = single([]); case 'fixed' T.x = fi([],true,16,15); T.y = fi([],true,16,13); case 'scaled' T.x = fi([],true,16,15,... 'DataType','ScaledDouble'); T.y = fi([],true,16,13,... 'DataType','ScaledDouble'); end end
有关详细信息,请参阅Separate Data Type Definitions from Algorithm。
更新测试脚本以使用类型表
更新测试脚本 mysum_test
以使用类型表。
-
对于第一次运行,请使用双精度值检查类型表和算法之间的关联。在声明
n
之前,添加T = mytypes('double');
-
更新对
buildInstrumentedMex
的调用以使用在数据类型表中指定的T.x
的类型:buildInstrumentedMex mysum -args {zeros(n,1,'like',T.x),T} -histogram
-
将
x
转换为使用在表中指定的T.x
的类型:x = cast(2*rand(n,1)-1,'like',T.x);
-
调用传入
T
的 MEX 函数:y = mysum_mex(x,T);
-
调用传入
T
的codegen
:codegen mysum -args {x,T} -config:lib -report
以下是更新后的测试脚本。
%% Build instrumented mex T = mytypes('double'); n = 10; buildInstrumentedMex mysum ... -args {zeros(n,1,'like',T.x),T} -histogram %% Test inputs rng default x = cast(2*rand(n,1)-1,'like',T.x); % Algorithm y = mysum_mex(x,T); % Verify results showInstrumentationResults mysum_mex ... -defaultDT numerictype(1,16) -proposeFL y_expected = sum(double(x)); err = double(y) - y_expected %% Generate C code codegen mysum -args {x,T} -config:lib -report
-
运行测试脚本并点击链接以打开代码生成报告。
生成的 C 代码与为原始算法生成的代码相同。原因是变量
T
用于指定类型,并且这些类型在代码生成时是恒定的;T
在运行时不使用,并且不会出现在生成的代码中。
生成定点代码
更新测试脚本以使用前面建议的定点类型并查看生成的 C 代码。
-
更新测试脚本以使用定点类型。用
T = mytypes('fixed');
替换T = mytypes('double');
,然后保存该脚本。 -
运行测试脚本并查看生成的 C 代码。
此 C 代码版本效率不是很高,它包含很多溢出处理。下一步是优化数据类型以避免溢出。
优化数据类型
使用定标双精度值来检测溢出
定标双精度值混合了浮点数和定点数。Fixed-Point Designer™ 将它们存储为保留定标、符号和字长信息的双精度值。由于所有算术都以双精度执行,因此您可以看到发生的任何溢出。
-
更新测试脚本以使用定标双精度值。用
T = mytypes('scaled');
替换T = mytypes('fixed');
-
再次运行测试脚本。
使用定标双精度值运行测试并显示报告。没有检测到溢出。
到当前为止,您只使用随机输入运行了测试脚本,这意味着测试并没有执行算法的整个运算范围。
-
找到输入的完整范围。
range(T.x)
-1.000000000000000 0.999969482421875 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 15
-
更新脚本以测试负边界情况。使用原始随机输入和测试整个范围的输入运行
mysum_mex
并聚合测试结果。%% Build instrumented mex T = mytypes('scaled'); n = 10; buildInstrumentedMex mysum ... -args {zeros(n,1,'like',T.x),T} -histogram %% Test inputs rng default x = cast(2*rand(n,1)-1,'like',T.x); y = mysum_mex(x,T); % Run once with this set of inputs y_expected = sum(double(x)); err = double(y) - y_expected % Run again with this set of inputs. The logs will aggregate. x = -ones(n,1,'like',T.x); y = mysum_mex(x,T); y_expected = sum(double(x)); err = double(y) - y_expected % Verify results showInstrumentationResults mysum_mex ... -defaultDT numerictype(1,16) -proposeFL y_expected = sum(double(x)); err = double(y) - y_expected %% Generate C code codegen mysum -args {x,T} -config:lib -report
-
再次运行测试脚本。
运行测试后,
y
的值会溢出定点数据类型的范围。showInstrumentationResults
建议对于y
采用新小数长度 11。 -
将测试脚本更新为对
y
使用具有建议的新类型的定标双精度。在myTypes.m
中,对于'scaled'
情况,使用T.y = fi([],true,16,11,'DataType','ScaledDouble')
-
重新运行测试脚本。
现在没有出现溢出。
为建议的定点类型生成代码
更新数据类型表以使用建议的定点类型并生成代码。
-
在
myTypes.m
中,对于'fixed'
情况,使用T.y = fi([],true,16,11)
-
更新测试脚本
mysum_test
,以使用T = mytypes('fixed');
-
运行测试脚本,然后点击“View Report”链接以查看生成的 C 代码。
short mysum(const short x[10]) { short y; int n; int i0; int i1; int i2; int i3; y = 0; for (n = 0; n < 10; n++) { i0 = y << 4; i1 = x[n]; if ((i0 & 1048576) != 0) { i2 = i0 | -1048576; } else { i2 = i0 & 1048575; } if ((i1 & 1048576) != 0) { i3 = i1 | -1048576; } else { i3 = i1 & 1048575; } i0 = i2 + i3; if ((i0 & 1048576) != 0) { i0 |= -1048576; } else { i0 &= 1048575; } i0 = (i0 + 8) >> 4; if (i0 > 32767) { i0 = 32767; } else { if (i0 < -32768) { i0 = -32768; } } y = (short)i0; } return y; }
默认情况下,
fi
算术在溢出和最接近舍入时使用饱和,导致代码效率低下。
修改 fimath 设置
要使生成的代码更高效,请使用更适合于生成 C 代码的定点数学 (fimath
) 设置:在溢出和向下取整时进行绕回。
-
在
myTypes.m
中,添加'fixed2'
case:case 'fixed2' F = fimath('RoundingMethod', 'Floor', ... 'OverflowAction', 'Wrap', ... 'ProductMode', 'FullPrecision', ... 'SumMode', 'KeepLSB', ... 'SumWordLength', 32, ... 'CastBeforeSum', true); T.x = fi([],true,16,15,F); T.y = fi([],true,16,11,F);
提示
您可以使用 MATLAB Editor
-
更新测试脚本以使用
'fixed2'
、运行脚本,然后查看生成的 C 代码。short mysum(const short x[10]) { short y; int n; y = 0; for (n = 0; n < 10; n++) { y = (short)(((y << 4) + x[n]) >> 4); } return y; }
生成的代码更高效,但是
y
经过移位以与x
对齐,失去 4 位精度。 -
为了解决这种精度丢失问题,将
y
的字长更新为 32 位,并保持 15 位的精度以与x
对齐。在
myTypes.m
中,添加'fixed32'
case:case 'fixed32' F = fimath('RoundingMethod', 'Floor', ... 'OverflowAction', 'Wrap', ... 'ProductMode', 'FullPrecision', ... 'SumMode', 'KeepLSB', ... 'SumWordLength', 32, ... 'CastBeforeSum', true); T.x = fi([],true,16,15,F); T.y = fi([],true,32,15,F);
-
更新测试脚本以使用
'fixed32'
并运行脚本以再次生成代码。现在,生成的代码非常高效。
int mysum(const short x[10]) { int y; int n; y = 0; for (n = 0; n < 10; n++) { y += x[n]; } return y; }
有关详细信息,请参阅Optimize Your Algorithm。
关注公众号: 只关于编程 (ID:allcoding) ,每天推送MATLAB学习最常见的问题,每天进步一点点,业精于勤荒于嬉。
打开微信扫一扫哦!