在过去的几年里,阿里集团平头哥陆续推出了几款RISCV处理器,有些处理器已经在产业界得到了应用,比如在某志的D1处理器中,就嵌入了平头哥的玄铁C906内核为 “芯”。RISCV虽然是一个开放标准,并且网络上也不乏一些开源核的RTL实现,但是商用的RISCV内核一般都是闭源的。不过令人惊喜的是,在今年十月,平头哥将其设计的四款RISCV内核开源,这其中就包括D1使用的C906核心。
玄铁 C906 是阿里巴巴平头哥半导体有限公司开发的低成本 64 位 RISC-V 架构处理器核,玄铁 C906 基于 64 位 RISC-V 架构,并对 RISC-V 架构进行了扩展增强。扩展增强包括:
1.指令集增强:重点针对内存访问、算术运算、位操作、Cache 操作四个方面进行增强,总计扩展130 条指令。同时,玄铁处理器开发团队在编译器层面对这些指令进行支持,除 Cache 操作指令外这些指令均可编译产生,包括 GCC 和 LLVM 编译.
2.内存模型增强:扩展内存页面属性,支持 Cacheable、Strong order 等页面属性,并在 Linux 内核上进行支持.
- 玄铁 C906 的主要体系结构参数包括:
- RV64IMA[FD]C[V]架构
- 平头哥指令扩展增强技术
- 平头哥内存模型增强技术
- 5 级整型流水线,单发按序执行
- 128 位的向量计算单元,支持 FP16/FP32/INT8/INT16/INT32 的 SIMD 计算.
C906是RV64位指令集,5 级按序单发射,8KB-64KB L1 Cache支持,不支持L2 Cache,支持半/单/双精度,VIPT四路组联L1数据缓存.
C906框图
![](https://img-blog.csdnimg.cn/f1e8654a9fa5493489f9182b38df4f0f.png)
开源地址:T-Head Semiconductor Co., Ltd. · GitHub
![](https://img-blog.csdnimg.cn/94f242c7a092441b850331035757f945.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
下面以openC906为例,介绍如何基于开源项目搭建一个处理器内核仿真平台。通过仿真平台可以获得CPU内部时钟级的运行信息,捕捉到程序运行任意时刻的信号,这对于一名系统工程师来讲,意义重大。下面开始。
环境准备
- ubuntu18.04
- iverilog,vvp,gtkwave工具
- 平头哥裸机GCC编译器
iverilog(vvp), gtkwave安装:
![](https://img-blog.csdnimg.cn/b82f81f9fe874458851edb8943367460.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
gcc:
平头哥芯片开放社区(OCC)
我选择的包为:Xuantie-900-gcc-elf-newlib-x86_64-V2.0.3-20210806.tar.gz,下载后解压:
![](https://img-blog.csdnimg.cn/cd59858f6b964ccfb6c9223dc53baaf1.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
获取RTL代码
git clone https://github.com/T-head-Semi/openc906.git
![](https://img-blog.csdnimg.cn/d0df1bbc7b834d438a40e287131ccc01.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
配置&修改
代码下来,不能直接仿真运行,必须要做一些修改。感觉平头哥在文档方面做得很差劲,比较不注意细节,GITHUB上文档就三言两语,即便为社区做了好事,在一些细节上不注意,也会遭到埋怨。下面就将这些平头哥文档中没有说明,但是必须要解决的问题列举出来。
首先看一下目录结构:
![](https://img-blog.csdnimg.cn/6f18f776586d4fb3b1d28baa63eef7ad.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
这个目录结构和GITHUB文档中给出的结构有所不同,sdk中缺少smart_run目录下的work目录。
![](https://img-blog.csdnimg.cn/067a28632fcc446b8c756d2bfdc41323.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
work目录需要手工创建,而文档中并没有说明,这是第一个问题, 没有work目录会导致后面运行make 失败,我们手工创建,创建之后目录列表是下面的样子:
![](https://img-blog.csdnimg.cn/315d9d1999f54069b75b4f0636eb950f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
其余问题我们在具体操作步骤中解决。
综合
RTL环境需要在csh中运行,csh有一些不便,比如不支持自动补全等等,不知道为何T-HEAD一定要将配置脚本写为.csh格式。
首先,配置工程路径环境变量,执行以下命令序列:
$ csh
% cd C906_RTL_FACTORY
% source setup/setup.csh
![](https://img-blog.csdnimg.cn/cbb7946855064770aa3a81e925b4d158.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
然后将工具链路径替换为真实的编译器路径:openc906/smart_run/setup/example_setup.csh
![](https://img-blog.csdnimg.cn/dbe3062a66614147b44e3929197ca83f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
之后切换到smart_run目录
![](https://img-blog.csdnimg.cn/c716d5dc4ace4f5080311c16cb83b39c.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
初始化工具链环境变量:
% source./smart_run/setup/example_setup.csh
可以看出这一步出了问题,这是第二个平头哥文档没有提到的问题,解决方式是删除example_setup.csh头部的版权声明部分,这里要留意。
![](https://img-blog.csdnimg.cn/934c788b5b9b49d9af1e36aec7649bc1.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/0e8934903efc463385889f49ff996f7d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
删除之后,再次运行,这次成功:
![](https://img-blog.csdnimg.cn/45f64a09fa0d4af7b928d8dc48f06bd3.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
之后是综合,进入到openc906/smart_run目录,执行make help:
![](https://img-blog.csdnimg.cn/aeea6cddb3ee4cfd842dfbcd208c7be0.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
综合的话,执行命令make compile
![](https://img-blog.csdnimg.cn/8c119df251394889a37f72f945101b34.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
这个错误,经过请教群友(GITHUB上有钉钉群二维码,扫码加入即可QA),经历过同样的问题的群友分享了解决方案,修改方式如下:将56行的static integer FILE修改为integer FILE.
![](https://img-blog.csdnimg.cn/1657c122eed345b4b5c7d23e0abd064f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
怀疑这个问题和iverilog的版本有关,在群里得到确认,既然构建系统中指定iverilog为默认的综合工具,在发布之前难道没有验证么?
![](https://img-blog.csdnimg.cn/d370adeaa072414a80ec12af75b6d4aa.JPG?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_16,color_FFFFFF,t_70,g_se,x_16)
不管怎样,流程还要继续,再次编译,这次成功执行:
在work目录下,生成了仿真VVP文件
![](https://img-blog.csdnimg.cn/9d6d60c3f32f4f55a1b289ace9866892.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
执行 make showcase,查看有哪些用例可以跑:
我们执行其中一个,执行make runcase CASE=coremark,又出错:
![](https://img-blog.csdnimg.cn/a45b4390f637434fa45d13a2af034289.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
这次出错的改法是,拷贝命令添加 -fr 选项:
![](https://img-blog.csdnimg.cn/64bbda9bc60448dd84453525f1ddf496.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
仍然有错误,看到了/bin/sh提示,想到莫非是shell解释器不对,修改/bin/sh指向bash
![](https://img-blog.csdnimg.cn/976f43ec6b694b328043c290a194ecf8.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_19,color_FFFFFF,t_70,g_se,x_16)
重新执行,新问题又来了,不过没关系,兵来将挡,水来土掩,如下图:
![](https://img-blog.csdnimg.cn/726b2188e77c4851989f0a4dd7d4434a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
可以看到编译过程会以LOG文件的形式被记录下来:coremark_build.case.log
![](https://img-blog.csdnimg.cn/b10d800ecb08417993185ccf8f2f7abf.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
在work目录中果然有同名文件:
![](https://img-blog.csdnimg.cn/6477612951a044e9a78de73a52600a49.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
我们打开这个文件,看里面有没有记录出错信息,找到最后,一条错误赫然出现在眼前:
Srec2vmem不知道是什么鬼,看名字,猜测它可能是将ELF的BINARY 转换为仿真TB可以加载的数据格式的工具,根据经验,如果它属于SDK中的工具,是由可能下载下来后不带有可执行属性,这也是LINUX的安全策略,我们强制修改其为可执行:
![](https://img-blog.csdnimg.cn/64a41694b71f45ec9c1305745ee685e9.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
至此,修改的文件包括:
![](https://img-blog.csdnimg.cn/8e18aed13e50474a83b95196fc91f598.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
之后再次执行make runcase CASE=coremark DUMP=on
DUMP=on表示我们需要生成VCD文件查看waveform.
Binggo! 错误尽除,VVP执行仿真产生波形VCD文件中,倒上一杯咖啡慢慢等吧!
![](https://img-blog.csdnimg.cn/59da072221854c6fb22a3141efac6ab2.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
执行结束后,查看波形:
用GTKWAVE打开波形文件:
![](https://img-blog.csdnimg.cn/921f118afcf54842b9e5e908c0ad5391.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGFwYW9mZG91ZG91,size_20,color_FFFFFF,t_70,g_se,x_16)
CPU内部对你已经毫无秘密可言了,用这种方法分析系统,只要你肯投入,相信没有解决不了的问题。
quartus ii综合仿真
C906是用Verilog开发的,可以用altera的综合仿真工具quartus ii进行布局布线综合仿真,并且得到方框图。
建立综合工程File->New Project Winzard .....解决编译错误,综合仿真,综合成功即可,不用关心布局布线失败,因为我也不清楚目标FPGA应该选择哪个。
上一步成功后,点击菜单Tools->NetList Viewers->RTL Viewer 打开综合方框图即可查看。
要注意,工程的名字要和你想要查看的顶层wrapper的名字相同,比如下图我需要看MMU的顶层结果,就选择对应的aq_mmu_top.v文件的模块aq_mmu_top作为工程名进行综合。
![](https://img-blog.csdnimg.cn/e35d0ec514024b7186df5bf25db2c026.png)
TLB wrapper结构翻译过来如下图,根据THEAD文档描述,C906 MMU采用两级TLB,第一级为uTLB,分别为指令I-uTLB和数据D-uTLB,第二级为jTLB,在处理器reset后,硬件会将uTLB和jTLB的所有表项进行无效化操作,软件无需初始化操作。
I-uTLB有10个全相联表项,每个表项可以混合存储4K,2M和1G三种大小的页面,取址请求命中I-uTLB时,当拍可以得到物理地址和相应权限属性。
D-uTLB有10个全相联表项,可以混合存储4K,2M,1G三种大小的页面,加载和存储请求命中D-uTLB时,当拍可以得到物理地址和相应权限属性。
jTLB为指令和数据共用,两路组相联结果,表项大小为128/256/512可配,可以混合存储4K,2M和1G三种大小的页面,u-TLB缺失,j-TLB命中时,最快3个cycle返回物理地址和相应权限属性。
![](https://img-blog.csdnimg.cn/518acacd5ebb4f3097f90dd5e7666209.png)
pmp wrapper 结构
![](https://img-blog.csdnimg.cn/77f53c019b4d4241986c7ffe251876b4.png)
微架构设计点:
官方生成最大取指位宽为128BIT,看代码中取INST实际只有固定的32BIT宽度。
![](https://img-blog.csdnimg.cn/43105eb7707a4ca684863e8b15adf64f.png)
但是前端IPACK到IBUF的数据通路确实是48BIT,IPACK和ICACHE相连,指令最终来源于ICACHE。
![](https://img-blog.csdnimg.cn/499c67ac8af34791b0c1d2beebc7a4a0.png)
总结:
C906默认使用了开源综合工具进行逻辑综合,算是好处理的。另外一个开源RISCV实现芯来的蜂鸟E200就没有那么容易了,需要Xilinx的Vivado将其综合编译为MCS bitstream文件才能运行在FPGA平台上,对于做软件的人来说,就没那么容易了,尤其是大厂的工具都很高级,授权方式尤其高级,别的不说,可能安装Vivado就会被搞得头破血流,能力所限,就不尝试了。下面是芯来的一些资料:
2. Hummingbirdv2 E203 Core — Hummingbirdv2 E203 Core and SoC 0.2.1 documentation
结束