PowerPoint 演示文稿
硬件综合设计讲解(1)
17计科袁福焱
2020/12/21
yuanfuya@qq.com
硬综任务说明
整体介绍
任务书说明
硬综流程
Trace调试
调试
常见错误
添加指令
冒险
异常处理
乘除法
搭建一个完整的计算机系统的步骤:
1. 实现一个CPU
2. 搭建一个SoC
3. 运行裸机程序
4. 移植操作系统
整体介绍
问题:我们实现的CPU能拿来干什么?
硬综涉及
实现MIPS CPU
RTL代码(软核)
MIPS 体系结构
微体系结构(实现)
MIPS32 Release1子集
指令集、异常模型(中断)、虚拟存储器、
编程模型(数据类型、寄存器、大小尾端、协处理器(CP0-CP3))
5级流水线、分支预测、Cache
HDL: VHDL, Verilog, system Verilog, Chisel
(硬综主要内容)
第一步是
首先我们实现的CPU是以代码的形式存在的,因此是一个软核,可以在不同的FPGA上移植,经过后端设计后也可以用于流片。而使用代码描述硬件需要使用硬件描述语言HDL,我们使用的是其中之一的Verilog语言。
然后,我们实现的是MIPS体系结构的CPU。更确切的说是其中的MIPS32 Release1分支的子集。一个指令集体系结构也就是ISA,不仅包含指令集,还包含许多其它的规定,如编程模型、异常处理、虚拟存储器、特权级等。当我们实现MIPS的CPU时,便是要实现这些规定。
最后,我们可以用多种方式实现同一个体系结构的CPU。就像AMD和intel的处理器都是x86架构的一样。CPU的实现被称为微体系结构,比如我们实现的5级流水线,分支预测、Cache都属于微体系结构的内容。
4
mycpu_top
图:2020龙芯杯cqu一队参赛作品(https://github.com/14010007517/2020NSCSCC)
SoC(System on Chip),在一个芯片上集成了一个基本完整的计算机系统。包含CPU,存储器,输入输出接口等。
搭建SoC
图: 龙芯杯system_test SoC结构
光有CPU,我们还没有办法运行程序。我们需要搭建一个SoC,SoC简单来说就是在一个芯片上集成了一个基本完整的计算机系统、包含CPU,存储器、输入输出等。
6
编程
裸金属(bare metal)程序。基于函数库开发、直接和外设打交道。
可以查看功能测试和性能测试的软件代码
片上总线
目的:将不同ip模块连接起来
AMBA互联总线
AHB (Advanced High-performance Bus) 高级高性能总线
ASB (Advanced System Bus) 高级系统总线
APB (Advanced Peripheral Bus) 高级外围总线
AXI (Advanced eXtensible Interface) 高级可拓展接口
搭建好SoC后,我们已经有了一个完整的硬件系统,可以运行软件了。但此时我们没有操作系统,运行的程序是裸金属程序。
我们可以查看一下功能测试和性能测试的代码。
功能测试全部都是汇编代码,性能测试则实现了一个微小的C标准库主要包括printf函数,字符串函数等。
7
图: 龙芯杯SoC_sram结构
(用于功能测试)
图: 龙芯杯SoC_axi_lite结构(用于功能测试和性能测试)
CPU从哪里开始运行?
程序(指令和数据)被提前加载到ram中
CPU复位地址0xbfc0_0000被映射到ram起始地址
程序的内存布局在链接时确定
8
启动:CPU reset → Bootloader→ os内核。把操作系统读取到内存
BIOS(ROM) → bootloader(MBR) → kernel(disk)(操作系统实验中的例子)
和操作系统密切相关:中断处理、虚拟存储器
操作系统移植
OS:实时操作系统(RTOS)、Linux、ucore
如果你不满足直接和硬件打交道的编程方式,就需要移植操作系统了。这里我就不仔细说明了,我目前也在做这方面的工作。
9
任务书说明
单周期10条指令(连接数据通路)
5级流水线(解决冒险)
1. 扩充指令到52条(扩展数据通路、乘除法)
2. 扩充至57条(添加异常处理、CP0)
3. 将CPU封装成axi接口
4. 添加cache模块
5. 扩展部分
– 完善Cache
– 实现TLB
硬综大致阶段
iii 处理器性能优化说明
流水线断流
分支指令
数据前推。将E阶段结果前推到D阶段
分支预测。
访存
优化cache
时序优化
逻辑延时
降低逻辑级数。乘法多周期完成、Cache划分流水线
布线延时
Cache从reg改为使用bram
添加指令
8 条逻辑运算指令
6 条移位指令
4 条数据移动指令
14 条算术运算指令
12条分支跳转指令
8 条访存指令
2 条内陷指令
3 条特权指令
按照功能划分(57条)
and, or
add, sub, slt, addi
beq, j
lw, sw
已经实现
(10条)
注意点
可进一步按照指令格式分为R-type和I-type。同一格式的指令数据通路基本可以复用
需要读写HILO: div(u), mult(u), mfhi(lo), mthi(lo)
jr指令增加新的pc来源,al结尾的指令增加写rf数据来源
需要对读取内存结果进行处理
需生成写内存的字节使能wen[3:0]
需要添加异常处理,添加CP0寄存器
运算指令
MIPS® Architecture For Programmers
Volume I-A: Introduction to the MIPS32® Architecture
MIPS® Architecture For Programmers
Volume II-A: The MIPS32® Instruction Set
MIPS® Architecture For Programmers
Volume III: The MIPS32® and microMIPS32™ Privileged Resource Architecture
MIPS手册
最详细、最权威
冒险
产生原因:指令间的相关性
数据冒险
先写后读RAW(read after write)
add t0, s0, s1
or t0, t0, s1
lw t0, offset(sp)
add t1, t0, s0
控制冒险
beq t0, t1, label
nop
addi t0, t0, 1
beq t0, t1, label
nop
lw无法在M阶段将数据前推给E阶段,需要暂停
addi的值没有从E阶段前推到D阶段,需要暂停
通过延迟槽,解决了分支跳转指令要在D阶段才能确定pc的问题
div t0, t1
mflo t2
mtlo t0
mflo t2
HILO相关
CP0相关
mtc0 t0, s0
mfc0 t1, s0
添加指令时可能会带来新的冒险
Tips: Hilo在M阶段上升沿写,在E阶段读取,可以不用处理冒险。
乘法
1. 乘法使用verilog乘号(不推荐)
2. 乘法使用xilinx ip——multiplier(推荐)
– 流水级数可以配置
– 时序较好(使用FPGA专门的资源)
– 有详细文档(只有20页)
3. 自己实现(推荐)
– 乘除法可以统一成一个模块
– 对接比较简单
除法
1. 使用《自己动手写CPU》中的除法器(雷思磊)(推荐)
– 需要观察该除法器的输入输出时序
2. 自己实现(推荐)
– 灵活度最高
– 对接较容易
3. 使用xilinx ip——divider generator
– 文档稍微复杂了一些(50页)
乘除法暂停
方式一:
暂停F, D, E
方式二:
暂停F, D, E, M, W
Tips:
li t0, 16
li t1, 2
div t0, t1
t0的数据来自第一条li指令W阶段的数据前推。t1的数据来自第二条li指令M阶段的前推。
只暂停F, D, E时,当M、W的指令流动到下一个阶段时,前推数据发生改变
二种方式流水线吞吐量基本一致
《自己动手写CPU》除法器示例波形图
(全暂停)
异常处理
直观上,硬件需要实现异常检测、异常跳转、保存返回地址、异常返回的机制
硬综需要实现以下7种异常
精确异常
In a precise exception CPU, on any exception we are pointed at one instruction (the exception victim). All instructions preceding the exception victim in execution sequence are complete; but it’s as if the exception victim and any successors were never started.
——《see mips run linux》, p108
将异常绑定到一条指令上
该指令之前的指令都会正常完成,之后的指令都相当于没有执行。
总结
一般是导致异常的指令(外部中断时不是)
24
EPC存储异常返回后重新开始执行时的地址。位于延迟槽内的指令,EPC存储为延迟槽的上一条指令的地址。
实现方式
否则,异常返回时,分支跳转指令没有起到作用
异常发生时只是做标记,在M阶段统一处理。
异常后面的指令无效,即不能对寄存器、HILO等CPU状态造成影响。
否则如果流水线不同阶段都产生异常,前面阶段的异常会被先处理。而非按照指令顺序。
清空指令、关闭寄存器写使能。特别的,停止乘除法运算(会修改hilo)
CP0寄存器
MIPS有4个协处理器
CP0包含系统控制寄存器(异常、TLB、cache)
CP1用于浮点数扩展
置CP0.Status.EXL位为1,CPU进入特权态且屏蔽所有中断
将例外处理返回后重新开始执行的指令PC填入到CP0.EPC寄存器中
如果发生例外的指令不在分支延迟槽中,则重新开始执行的指令PC就等于发生例外的指令的PC;
否则重新开始执行的指令PC等于发生例外的指令的PC-4(即该延迟槽对应的分支指令的PC),且将CP0.Cause.BD位置为1。
将例外类型编码写入CP0.Cause.ExCode域。
有些异常还需要设置其它CP0寄存器。
例如,发生地址错例外时,将触发例外的错误PC值或load/store指令的虚地址写入CP0.BadVaddr寄存器中
处理器跳转至对应的例外入口开始取指。
处理器硬件响应例外的一般性过程
算数溢出异常(Ov)
产生指令:add, addi, sub
提示:
addiu和addi都是有符号扩展,唯一区别在于addiu不产生异常
正+正=负、负+负=正
正-负=负、负-正=正
方式一
方式二(trick)
{carry_bit, result} = {a[31], a} + {b[31], b};
{carry_bit, result} = {a[31], a} – {b[31], b};
overflow = carry_bit ^ result[31]
中断(int)
6个硬件中断IP7-IP2
2个软件中断IP1-IP0
全局中断使能IE
中断屏蔽位IM7-IM0
硬件中断来自外部,mycpu_top需要增加输入
int = status_ie & |(status_im[7:0] & cause_ip[7:0])
eret指令
eret可以看做是一条分支跳转指令,也可以当作一种异常来处理
硬综任务说明
整体介绍
任务书说明
硬综流程
Trace调试
调试
常见错误
添加指令
冒险
异常处理
乘除法
添加指令
axi接口支持
添加基本cache
(52条)使用lab4工程,导入funcTest_independent下的coe,独立测试6类指令。(通过观察仿真波形图中寄存器的值是否与汇编代码中注释一致)
(52条)使用func_test_v0.03\soc_sram_func工程(将mycpu_top封装成sram接口),通过64个测试点。(基于trace调试)
(57条)添加异常处理、CP0、剩余5条指令,功能测试通过89个测试点。
将cpu封装成axi接口。使用func_test_v0.03\soc_axi_func,通过89个测试点。
使用perf_test_v0.01\soc_axi_perf,通过性能测试。
实现直接映射写直达的cache
完善cache或实现TLB
扩展部分(加分)
上板测试
使用n4ddr下的func_test和perf_test工程,生成bitstream,上板观察是否成功。不成功则仍需继续仿真调试。性能测试上板成功则可以计算CPU性能得分,性能分和扩展部分cache的加分有关。
上面的每个部分根据完成程度,按照评分标准给分
硬综流程
流程怎么来的?
1. 加了指令如何测试?
(1)搭了个简单的环境,编写了简单的tb,跑简单的代码,人工看波形图。
(2)编写了更充分的测试程序,测试量大,必须使用自动化测试——trace比对机制。
为了上板可以交互,soc添加了外设。
SoC, testbench, soft一起形成了func_test环境
soc
testbench
soft
testbench
– 实现了Trace比较机制
soft
89个测试点
指令
延迟槽
异常
延迟槽异常
soc_sram
为了上板能交互,soc包含外设。
func_test环境
soc_axi_lite
Soc采用axi接口互联
35
2. 如何测试axi接口的正确性?
使用axi接口的soc,同样运行功能测soft(使用func_test/soc_axi_func)
3. 如何测试cpu性能?
axi接口的soc保持不变,编写性能测试软件,形成了perf_test环境
没有提供trace用于比对
soft
10个基准测试程序(bench)
soc_axi_lite
perf_test环境
testbench
硬综任务说明
整体介绍
任务书说明
硬综流程
Trace调试
调试
常见错误
添加指令
冒险
异常处理
乘除法
调试
熟悉vivado的仿真窗口的一些操作
选择Scope,在Objects中右键添加变量到波形图
按住ctrl+鼠标左键,可以依次选择多个变量
鼠标左键+按住shift+鼠标左键,一次选择一列变量
跳转到变量的上(下)一次变化位置
搜索变量值
设置一个Marker,并在标记间跳转
改变变量的颜色、进制。
对波形图的变量进行整理,对变量进行分组!
要调哪个模块就拉取哪个模块的变量。比如要调寄存器堆,那么就把寄存器堆的时钟、写使能、写数据全部都放在一个分组里。
配置好的仿真文件可以保存成wfcg文件,下次再次使用!
养成从错误倒推的思维方式。
先找直接错误,再根据代码找导致这个错误的原因,拉取相关变量。
优化调试环境 = 提升调试效率!!!
Trace调试
参考A11_Trace比对机制使用说明_v1.00.pdf
介绍了trace比对原理,testbench代码说明,功能测试soft运行说明
mycpu_top需要输出debug信号
debug_wb_pc: CPU写回级(wb)的PC
debug_wb_rf_wen: wb级的写寄存器堆(rf)使能
debug_wb_rf_wnum: wb级写寄存器堆(rf)目的寄存器号
debug_wb_rf_wdata: wb级的写回的目的操作数
ref信号为X
testbench路径问题,改为绝对路径
Tcl控制台输出
检查下面的表达式是否为真
Testbench读取trace文件到ref信号中
trace共有三处对比:pc、num、data
PC不对应
在反汇编文件(test.s)中搜索pc地址
找到第一条引起分叉的指令
num不对
数据通路不对;后面基本不会遇到这个错误
data不对
普通指令,看ALU和前推
访存指令,lw不对,找同一个address的最后一个sw指令
看《 A09_CPU仿真调试说明》
有Z,一定没连线 (变量未赋值、赋值时信号宽度不一致等等)
有X,要么没初始化;要么多驱动
不管有没有错。Z、X都不该有;如果有错,先看Z、X,大概率是错误原因。
调试技巧
Tips: 如果9fc搜索不到就搜索bfc,反之亦然(原理和MIPS地址空间映射有关)
常见错误
这是一条lw指令,读取到的数据错误,正确值为0x0000_aaaa,读取值为0x0000_0000。
错误原因:
lw读取的地址是0xhbfaf_f02c,该地址对应着SoC中拨码开关的值。但我们CPU目前发出的地址是虚拟地址,而1x2bridge是根据物理地址进行路由转发的。因此我们需要实现规定的固定地址映射方案(见A03_“系统能力培养大赛”MIPS指令系统规范_v1.01)
ref_code里提供的mmu模块
工具
版本管理:git版本控制工具
结对编程:VS code Live Share 扩展
极力推荐
同时也方便实验报告写日志
提问的方式
提供尽可能多的信息。如处于硬综的哪个阶段,用的哪个工程,控制台输出,仿真的波形图等等。
先看文档!!!
How To Ask Questions The Smart Way (catb.org)
推荐阅读
不要只描述问题
Q & A
/docProps/thumbnail.jpeg