目前使用的DDR PHY中都有可以调整DQ或者DQS信号线上的延时功能,该延时就是用来补偿DDR走线不等长的问题。特别是在两层PCB上,为了走线方便,DQ信号线的长度差异很大,如果芯片内部不做补偿,窗口将会是非常的小。
如图3-1所示,DDR的时序窗口为各个DQ信号的交集部分,如果不做DDR Training交集会比较小,做过DDR Training后时序窗口将会增大。
HiDdrTraining工具调整的原理与Fastboot下调整的原理相似,不同点就是把boot下调整使用的DDRT或者其它业务模块(VEDU)更换为实际的业务,这样芯片内部的干扰和DDR的压力更大,Training得到的结果也更准确。
以Hi3716CV200为例,Training时按照byte为一组,因为DQS信号的调整会影响到该byte内部的所有窗口,且DQ信号的调整范围比较大(32级BDL(bit delay line),每个级别25ps),因此不对DQS信号进行调整,直接使用boot表格中的DQS信号的配置。只调整DQ信号的BDL值。
调整的步骤如下:
在linux环境下配置测试业务:PIP+TDE+GPU+DDRT,设置开机自动启动业务。开启watchdog功能设置5秒喂狗一次,如果没有喂狗则watchdog会对单板进行重启。
读取DQ信号的BDL的默认配置。
从默认的DQ BDL开始,增加BDL值,等待30s(时间可调)。
l 如果30s没有检测到单板重启,记录该BDL OK。
l 如果30s检测到单板重启,记录该BDL 错误。
重复步骤 3直到BDL的最大值。
从默认的DQ BDL开始,逐渐减小BDL直到单板重启,等待30s。
l 如果30s内没有检测到单板重启,记录该BDL OK。
l 如果30s内检测到单板重启,记录该BDL 错误。
重复步骤 5直到BDL的最小值。
统计记录OK的BDL级数作为该DQ信号的窗口大小,取中间的BDL值作为最优配置。
l Hi3716CV200
DQ信号可调32级BDL窗口,不需要调整DQS的BDL窗口;
l Hi3716MV300
DQ与DQS只可以调整8级BDL窗口,所以调整时使用DQS与DQ的组合以后的15级BDL窗口;
l Hi3716CV100和Hi3531读写方向调整的级别不一样,Hi3716CV100写方向可以调整29级BDL窗口,读方向可以调整15级BDL窗口。
Hi3716CV100 DQ/DQS组合BDL级别
写窗口级别 |
读窗口级别 |
DQS级别 |
DQ级别 |
0 |
- |
关 |
7 |
1 |
- |
关 |
6 |
2 |
- |
关 |
5 |
3 |
- |
关 |
4 |
4 |
- |
关 |
3 |
5 |
- |
关 |
2 |
6 |
- |
关 |
1 |
7 |
0 |
0 |
7 |
8 |
1 |
0 |
6 |
9 |
2 |
0 |
5 |
10 |
3 |
0 |
4 |
11 |
4 |
0 |
3 |
12 |
5 |
0 |
2 |
13 |
6 |
0 |
1 |
14 |
7 |
0 |
0 |
15 |
8 |
1 |
0 |
16 |
9 |
2 |
0 |
17 |
10 |
3 |
0 |
18 |
11 |
4 |
0 |
19 |
12 |
5 |
0 |
20 |
13 |
6 |
0 |
21 |
14 |
7 |
0 |
22 |
- |
1 |
关 |
23 |
- |
2 |
关 |
24 |
- |
3 |
关 |
25 |
- |
4 |
关 |
26 |
- |
5 |
关 |
27 |
- |
6 |
关 |
28 |
- |
7 |
关 |
Hi3716MV300 DQ/DQS组合BDL级别
写窗口级别 |
读窗口级别 |
DQS级别 |
DQ级别 |
0 |
0 |
7 |
0 |
1 |
1 |
6 |
0 |
2 |
2 |
5 |
0 |
3 |
3 |
4 |
0 |
4 |
4 |
3 |
0 |
5 |
5 |
2 |
0 |
6 |
6 |
1 |
0 |
7 |
7 |
0 |
1 |
8 |
8 |
0 |
2 |
9 |
9 |
0 |
3 |
10 |
10 |
0 |
4 |
11 |
11 |
0 |
5 |
12 |
12 |
0 |
6 |
13 |
13 |
0 |
7 |
Hi3716CV200 DQ BDL级别
写窗口级别 |
读窗口级别 |
DQ级别 |
0 |
0 |
0 |
1 |
1 |
1 |
2 |
2 |
2 |
3 |
3 |
3 |
4 |
4 |
4 |
5 |
5 |
5 |
6 |
6 |
6 |
7 |
7 |
7 |
8 |
8 |
8 |
9 |
9 |
9 |
10 |
10 |
10 |
11 |
11 |
11 |
12 |
12 |
12 |
13 |
13 |
13 |
14 |
14 |
14 |
15 |
15 |
15 |
16 |
16 |
16 |
17 |
17 |
17 |
18 |
18 |
18 |
19 |
19 |
19 |
20 |
20 |
20 |
21 |
21 |
21 |
22 |
22 |
22 |
23 |
23 |
23 |
24 |
24 |
24 |
25 |
25 |
25 |
26 |
26 |
26 |
27 |
27 |
27 |
28 |
28 |
28 |
29 |
29 |
29 |
30 |
30 |
30 |
31 |
31 |
31 |
----结束
由于现在所有的芯片已经预置了脚本,可供用户直接使用,如果需要更新脚本的用户可以参考工具的详细执行流程来自行开发脚本,运行的步骤如下:
l 当registergroup中只定义了一个register时,以下称为Single。
l 当registergroup中定义了多个register时,以下称为Multiple。
开始读取配置文件。
启动watchdog。
执行kocommand,kocommand从首选项配置中加载,执行regtool命令。
读取需要遍历的寄存器保存起来,记为初始值。
处理loops(loops对应于一个byte),然后循环处理每一个loops里面的loop(loop对应于dq信号)。
处理loop_level_begin。
判断当前registergroup的initvalue是否为true,为true,则打印当前loop中所有寄存器的初始值并保存。
l 处理single。
当defaultvalue等于-1
当设置了minvalue(最小DQ BDL级别):
− 循环更新register的值(register值即为DQ BDL级别),写回设备,并检测设备是否重启。
− 更新规则:当前值=当前值-1(当前值的初始值根据配置的位范围以及寄存器从板端读取的值确定。)
− 循环条件:当前值>=minvalue。
− 循环执行一次,检测设备是否重启,等待时间可在UI界面上的超时时间文本框控制,并输出当次执行结果。
− 循环结束后,当前registergroup中的所有寄存器会进行复位。
当设置了maxvalue:(最大DQ BDL级别)
− 循环更新register的值,写回设备,并检测设备是否重启。
− 更新规则:当前值=当前值+1(当前值的初始值根据配置的位范围以及寄存器从板端读取的值确定。)
− 循环条件:当前值<=maxvalue。
− 循环执行一次,检测设备是否重启,等待时间可在UI界面上的超时时间文本 框控制,并输出当次执行结果。
− 循环结束后,当前registergroup中的所有寄存器会进行复位。
当defaultvalue不等于-1
将默认值写入设备,检测设备是否重启,等待时间可在UI界面上的超时时间文本框控制,并输出当次执行结果。写入成功后,当前registergroup中的寄存器会等待其所在的group中所有的registerGroup内全部寄存器执行结束后,这个寄存器的值才会进行复位。
l 处理Multiple
当设置了minvalue:
− 循环更新register的值,写回设备,并检测设备是否重启。
− 更新规则:当前值=当前值-1(当前值的初始值根据配置的位范围以及寄存器从板端读取的值确定,每一个寄存器的当前值是独立的)。
− 循环条件:寄存器中当前值的最小值 > minvalue。
− 循环执行一次,检测设备是否重启,等待时间可在UI界面上的超时时间文本框控制,并输出当次执行结果。
− 循环结束后,当前registergroup中的所有寄存器会进行复位。
当设置了maxvalue:
− 循环更新register的值,写回设备,并检测设备是否重启。
− 更新规则:当前值=当前值+1(当前值的初始值根据配置的位范围以及寄存器从板端读取的值确定,每一个寄存器的当前值是独立的)。
− 循环条件:寄存器中当前值的最大值< maxvalue。
− 循环执行一次,检测设备是否重启,等待时间可在UI界面上的超时时间文本框控制,并输出当次执行结果。
− 循环结束后,当前registergroup中的所有寄存器会进行复位。
如果在执行过程中boot没有自动重启,工具将会提示手动重启。
所有loops中loop_level全部执行完毕后,查找合并reg文件,处理并打印保存最优值结果。详细可参考下面说明。
l 求解最优值的规则
根据每一个loop的执行结果集合,每一个loop取一个最优值。
− 执行结果状态无Fail时,取结果集合最中间值作为best值。
− 存在一个Fail时,判断Fail距开头的间距和Fail距结尾的间距的大小,哪个间距最大,得到间距最大部分,取最大部分的中间值作为best值。
− 存在多个Fail时,判断开头离最近Fail的间距,结尾离最近Fail的间距,以及每个Fail之间的间距,哪个间距最大,得到间距最大部分,取最大部分的中间值作为best值。
l 处理结果
− 如果Training类型为byteTraining,工具将直接把每个loop的执行结果以及最优值打印到控制台上。
− 如果Training类型为bitTraining,工具将会根据脚本的配置对每个loop的最优值进行处理。具体处理步骤如下,分两种情况处理:
loops指定了最大值寄存器。
Ø 取到loops指定寄存器在所有loop中的最优值的最大值。
Ø 取到每个loop指定的寄存器的关键值。
Ø 计算得到最后整个loops的最优值组合。最优值组合包含了每个loop的关键最优值,关键最优值的计算公式为:(每个loop的关键最优值=最大值-每个loop中loops指定寄存器的最优值+每个loop的关键值)
Ø 计算DM值,把每个loop的关键最优值相加,取平均值,小数情况下四舍五入取整。
loops没有指定最大值寄存器。
Ø 取到每个loop指定的寄存器的关键值。
Ø 计算得到最后整个loops的最优值组合。最优值组合包含了每个loop的关键最优值,每个loop的关键最优值=每个loop的关键值。
Ø 计算DM值,把每个loop的关键最优值相加,取平均值,小数情况下四舍五入取整。
最后把bittraining的执行结果打印出来,打印内容包括:每一个loops的最优值组合以及DM值。
l 结果格式
只是作为打印结果格式的参考,执行数据应以工具执行的数据为准。dqs0,dq0,dq1,dq2,dq3,dq4,dq5,dq6,dq7表示寄存器的名称。寄存器名称必须在loop的description中存在定义。
每次执行一个loop,先打印description。以single循环,默认的dqs为3为例,
以single循环,默认的dqs为3举例
dqs0 |
dq0 |
dq1 |
dq2 |
dq3 |
dq4 |
dq5 |
dq6 |
dq7 |
Result |
7 |
0 |
0 |
0 |
0 |
2 |
2 |
2 |
1 |
fail |
6 |
0 |
0 |
0 |
0 |
2 |
2 |
2 |
1 |
ok |
5 |
0 |
0 |
0 |
0 |
2 |
2 |
2 |
1 |
ok |
4 |
0 |
0 |
0 |
0 |
2 |
2 |
2 |
1 |
ok |
以Multiple循环举例
dqs0 |
dq0 |
dq1 |
dq2 |
dq3 |
dq4 |
dq5 |
dq6 |
dq7 |
Result |
3 |
1 |
1 |
1 |
1 |
3 |
3 |
3 |
2 |
ok |
3 |
2 |
2 |
2 |
2 |
4 |
4 |
4 |
3 |
ok |
3 |
3 |
3 |
3 |
3 |
5 |
5 |
5 |
4 |
fail |
到第一个fail的就结束这个小项的循环,取中间一行为最佳值,也就是4 排(0 0 0 0 2 2 2 1)组,同时打印出最佳值和默认值,如表3-6 。
输出最佳值和默认值
值类型 |
dqs0 |
dq0 |
dq1 |
dq2 |
dq3 |
dq4 |
dq5 |
dq6 |
dq7 |
默认值 |
3 |
0 |
0 |
0 |
0 |
2 |
2 |
2 |
1 |
最佳值 |
4 |
0 |
0 |
0 |
0 |
2 |
2 |
2 |
1 |
当training类型为bittraining时,还会打印以下内容,无最大值时,将不会打印最大值那一列。
− MaxRegister: loops指定的寄存器名称
− MaxValue: loops指定的寄存器的最大值
有效值组合举例(最大值列和每个loop的关键寄存器值)
loop名称 |
最大值 |
关键值1 |
关键值2 |
Loop1 |
0 |
0 |
- |
Loop2 |
0 |
- |
0 |
整个loops的最佳值组合举例
值类型 |
最大值 |
关键值1 |
关键值2 |
最佳值: |
0 |
0 |
0 |
DM:0
l 查找合并
从输入Reg文件中查找匹配相同地址进行合并,并且更新合并后的值。
保存结果:
training执行失败或中途取消操作,将不会保存结果到结果文件。
training正确执行成功后,保存training的最优结果到一个reg.bin文件,reg.bin文件的格式有下面结构体连接而成,如我们要把rddqs0和rddqs1的值都设为4 (address="0x10100b4c" start="0" end="2", name="rdqs1" address="0x10100b4c" start="3" end="5"),那么寄存器0x10100b4c的值就应该修改为0x24。
struct regentry {
unsigned int reg_addr; ---- 寄存器地址
unsigned int value; -------寄存器的值
unsigned int delay;
unsigned int attr;
};
Reg文件格式
Struct |
Struct |
Struct |
..... |
Struct |
regentry |
regentry |
regentry |
..... |
Struct |
l training、commands只能出现一次。
l training节点为根节点,training 包含commands和多个loops节点。
l commands节点里面可以包含多个command节点。
l loops里面包含多个loop节点,loop里面包含多个group节点。
l group里面包含多个registergroup节点。
l registergroup包含多个register节点。
l training节点包括mode属性,mode属性定义了Training模式,mode属性值可选"byte"和"bit"。两者只能选其一。
说明:当training节点上不包含mode属性时,默认mode类型为“byte”。
l command节点包括value属性,value属性定义了执行的命令字符串,value属性值不能为空,当命令中包括符号时,必须使用此符号的html转义符。
l loops节点上包括max属性,max属性定义了loops指定的最大寄存器的名称。
说明:
− 当mode为“bit”时, loops节点可包含max属性,也可不包含。当包含max属性时,定义的属性值不能为空。max属性的存在性会使工具对bittraining结果有不同的处理。
max属性值定义的最大寄存器必须在当前loops的每一个loop都存在定义。
− 当mode为“byte”时,因为max属性只在bit模式时才起作用,所以byte模式下max属性可定义也可不定义。
l loop节点包含key和description属性,不能为空。
− key属性定义了当前loop指定的关键寄存器名称;
− description属性定义了当前loop节点下的所有寄存器名称,每个loop节点中所有寄存器的名称必须在loop节点上的description中存在定义,否则无效。
− description属性值中定义的每个寄存器名称之间用英文逗号分隔,第一个名称将被忽略,名称不能存在重复值。如: 第一个“read”将被忽略,实际的寄存器名称为:“rdqs0,rdq0,rdq1,rdq2,rdq3,rdq4,rdq5,rdq6,rdq7” 。
说明:
− 当mode为“bit”时,loop节点上的key属性必须定义,且 保证定义的key属性值在当前loop中的任意一个regsitergroup中的register列表中存在定义。
− 当mode为“byte”时,因为key属性只在bit模式时才起作用,所以byte模式下key属性可定义也可不定义。
l group节点无属性值。
l registergroup节点包括initvalue、sequence、maxvalue,minvalue和defaultvalue属性。如下:
− initvalue值指定当前registergroup是否只是输出初始值,值可取true或false,默认为false,当为true时,该registergroup的其他属性全部无效,加载时不做校验;否则,加载并验证其他属性配置。
− sequence值控制registergroup结果的排列输出顺序,值不能为空;值可取true或false,为true时,顺序排列输出,否则,逆序排列输入;
− maxvalue定义了当前节点下所有寄存器循环执行的最大值;
− minvalue 定义了当前节点下所有寄存器循环执行的最小值;
− defaultvalue定义了当前节点下所有寄存器的默认值;
说明:
− registergroup节点中的maxvalue和minvalue属性定义时,只能二选一。即registergroup节点上maxvalue和minvalue属性任何时候只能存在一个。
− 除initvalue为true外,maxvalue,minvalue和defaultvalue三者必须定义一个。
− register节点下包括name、address、start和end属性,name定义了当前寄存器的名称;address定义了寄存器地址;start定义了截取寄存器的起始位置;end定义了截取寄存器的结束位置。
l 必须包含xml的声明,编码格式为UTF-8。
l 脚本文件所有节点均是成对出现,且脚本中所有节点名称为小写,书写必须符合xml规范。
l 在loop节点下,当两个寄存器的address,start和end属性值都相同时,那么这两个寄存器的name属性值也必须相同,否则,当有一项不同时,两个寄存器的name属性值必须不同。
l 脚本文件后缀名建议为“.xml”,脚本文件可以参考已经提供的xml文件作为样例参考。