0%

CPU功能测试与验证

CPU功能测试过程中遇到的问题及解决方案,包括longlong测试、内存对齐等问题的分析。

longlong 的cpu测试有时候过不了

1
long long test_data[] = {0, 1, 2, 0x7fffffffffffffffLL, 0x8000000000000000LL, 0x8000000000000001LL, 0xfffffffffffffffeLL, 0xffffffffffffffffLL};

longlong的打印

在处理 long long 类型的负数时,特别是极值(如 0x8000000000000000LL),直接取反操作 value = -value; 可能会导致溢出问题。因为 0x8000000000000000LL 是 long long 类型的最小值,其绝对值超出了 long long 类型的正数范围
longlong打印问题

1
2
3
4
5
6
long long value;
// Set '-' for negative decimals.
if (value < 0 && base == 10) {
*str++ = '-';
value = -value;
}

使用无符号类型:在处理负数时,将其转换为无符号类型 unsigned long long,以避免溢出问题。
longlong打印修复

1
2
3
4
5
6
7
8
unsigned long long uvalue;
// Set '-' for negative decimals.
if (value < 0 && base == 10) {
*str++ = '-';
uvalue = (unsigned long long)(-value);
} else {
uvalue = (unsigned long long)value;
}

longlong必须8字节对齐

如果只是四字节对齐的话,longlong的指针8字节对齐,但flash中存储的longlong数据不会8字节对齐。

1
2
3
4
5
6
7
8
.data : {
_data_start = .;
*(.data*)
*(.sdata*)
/* *(.data) */
_data_end = .;
. = ALIGN(4);
} > sdram AT >flash

可以看到数组指针8字节对齐,但数组数据没有
数据未对齐
通过8字节对齐,让longlong对齐

1
2
3
4
5
6
7
8
.data : {
_data_start = .;
*(.data*)
*(.sdata*)
/* *(.data) */
_data_end = .;
. = ALIGN(8);
} > sdram AT >flash

数据已对齐

调试信息

4-2-1访存未对齐

问题现象展示

1
2
3
4
5
6
7
8
9
a0000180:	fe042823          	sw	zero,-16(s0)
a0000184: 0900006f j a0000214 <main+0x1d0>
a0000188: ff042783 lw a5,-16(s0)
a000018c: 00279793 sll a5,a5,0x2
a0000190: 00178713 add a4,a5,1
a0000194: 00001797 auipc a5,0x1
a0000198: 4ec78793 add a5,a5,1260 # a0001680 <mem>
a000019c: 00f707b3 add a5,a4,a5
a00001a0: 0007a783 lw a5,0(a5)
1
2
3
4
5
6
7
8
9
10
11
12
unsigned short mem[] = {
0x0, 0x0258, 0x4abc, 0x7fff, 0x8000, 0x8100, 0xabcd, 0xffff
};
unsigned lwlr_ans[] = {
0xbc025800, 0x7fff4a, 0xcd810080, 0xffffab
};
for(i = 0; i < ((LENGTH(mem) / 2) - 1); i ++) {
unsigned x = ((unsigned*)((void*)mem + 1))[i];
unsigned y = lwlr_ans[i];
printf("x=%x,y=%x\n",x,y);
check(x == lwlr_ans[i]);
}

访存未对齐1
访存未对齐2
使用nemu编译实锤编译出了非对齐访存

1
2
3
[mtrace] read data 0xbc025800 from pmem 0x800012d5
[mtrace] read data 0xfef42223 from pmem 0x80000178
[mtrace] write data 0xbc025800 to pmem 0x80009fd4

difftest忘开了,不然也不至于找这么半天
difftest问题

gcc开启参数-mstrict-align

但是使用下面编译器,参数无效,还能编译出非对齐访存,得使用上面的

1
2
3
CROSS_COMPILE := /opt/riscv/bin/riscv64-unknown-elf-
#CROSS_COMPILE := /opt/riscv/bin/riscv64-unknown-linux-gnu-
COMMON_CFLAGS := -fno-pic -march=rv64g -mcmodel=medany -mstrict-align

发现是写内存代码有问题,解决了就好了,编译器都可以使

直接#include<stido.h>就是使用的gnu的stdio.h