Chisel后篇-Riscv-Rocketchip使用介绍
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Chisel后篇-Riscv-Rocketchip使⽤介绍
rocket-chip generator介绍
rocket-chip generator的⼀级⽬录结构:
bootrom : 在BootROM的bootloader第⼀阶段所使⽤的代码
csrc Verilator: 仿真⽤的C代码
emulator Verilator :⽤来编译和跑仿真的⼯作⽬录
project Scala: 构建⼯具sbt⽤来构建Scala的⼯作⽬录
regression: 定义的持续的整合和⼀套nightly regression
scripts: ⽤来分析仿真的输出或者处理代码⽂件的内容
vsim VCS: ⽤来编译和跑仿真的⼯作⽬录
vsrc Verilog: 代码,包含接⼝、测试框架和Verilog过程接⼝VPI
chisel3 :包含Chisel⾃定义的各种类和规则,⽤来⽣成RTL
firrtl: 存放Chisel编译器处理代码⽽⽣成的⼀种中间表⽰,由中间表⽰能⽣成Verilog代码或C++代码
hardfloat: ⽤chisel写成的浮点单元
riscv-tools: ⽀持RISC-V的⼀套软件,与⽣成RTL有关
torture: ⽤来⽣成压⼒测试所需的⼀些随机指令
src/main/scala: 构筑rocket-chip的代码:
rocket-chip generator电路构筑代码的⽬录结构:amba amba: 协议的实现代码,包括AXI4,AHB-lite,APB
config: 提供能配置Generator的Scala的接⼝
coreplex: 包含Rocket核、系统总线、coherence agents、debug设备、中断处理、⾯向外部的外设、时钟同步处理和TileLink到外设总线转换
devices: ⼀些外设,包括debug模块和各种挂在TileLink的从设备
diplomacy: ⽤来扩展Chisel,通过允许对硬件进⾏两个阶段的阐述,可以让参数在模块之间协调传递
groundtest: ⽣成可综合的硬件测试平台,通过发出随机的访问存储器指令流,进⾏对核外的存储器系统进⾏压⼒测试
jtag: ⽤来⽣成JTAG总线接⼝
regmapper: ⽤来⽣成带有能访问内存映射寄存器的标准接⼝的从设备
rocket: ⽤来⽣成顺序核Rocket、L1指令cache和L1数据cache
tile: 包含可以与Rocket核组成tile的组件,如FPU和RoCC协处理器
tilelink: ⽤来⽣成TileLink总线(协议),包含⼀些适配器和转其他总线(协议)的转换器
system Rocket Chip的顶层代码包,同时也是⽤作测试的硬件平台的顶层代码包
unittest: ⽤作⽣成硬件测试平台来测试单独的⼀个个模块
util: 提供⼀些能被其他代码包调⽤的通⽤的Scala和Chisel结构
如何配置⼀个⾃定义的rocket-chip?
这节的主要内容是教⼤家如何⾃由配置⼀个rocket-chip。
以下是我对rocket-chip修改后实现的特殊功能(部分我会以例⼦的形式进⾏说明):
1、将reset_vector信号引到顶层,可以根据该信号使rocket-chip从不同地址启动。
2、在rocket-chip的顶层引出⼀套采⽤Tilelink的SRAM,这套SRAM按物理地址访问。
3、修改各总线(mem/MMIO)的物理访问地址。
4、将各总线(mem/MMIO)的AXI4协议改为AHB协议。
5、将local interrupt的信号引到rocket-chip的顶层,使除了PLIC外,还能使⽤local interrupt。
6、修改ROCC的功能,扩展custom0、custom1、custom2和custom3的功能。
7、加⼊DCache enable的CSR寄存器,并实现相应功能,使DCache的功能变为可选。
现在先对rocket-chip的Scala代码进⾏简单的介绍。
我决定以从顶到底的⽅式解释rocket-chip的Scala代码,此外我不会每个Scala⽂件都⼀⼀说明,某些测试的Scala⽂件我会跳过的。
⾸先说明的是/rocket-chip/src/main/scala/system⽬录:
Generator.scala & RocketTestSuite.scala 这两个⽂件是测试相关的,所以我不做说明。
第⼀个看的Scala⽂件是:TestHarness.scala
带//注释的就是解释。
下图是 TestHarness.scala ⽣成的连接图。
第⼆个看的Scala⽂件是:ExampleRocketSystem.scala
可以知道 TestHarness.scala 就是testbench,⽽ ExampleRocketSystem.scala ⽣成的才是我们关注的SOC, ExampleRocketSystem.scala 包括Core以外的其他外设&总线。
第三个看的Scala⽂件是:Configs.scala
TestHarness.scala 就是testbench,⽽ ExampleRocketSystem.scala 就是SOC的层次,包括Core以外的其他外设&总线,Configs.scala 就是核⼼Core的配置。
Configs.scala 的配置⽐较多,我挑⼏个来说明。
rocket-chip generator使⽤
在src/main/scala/coreplex/Configs.scala的类都是构筑rocket-chip的“部件”。
需要在src/main/scala/system/Configs.scala中将“部件”类和“底板”类BaseConfig组合起来,每⼀个都是⼀种配置⽅案。
具体的⽅法就是利⽤“++”这个函数,写法参考该⽂件的其他类写法即可。
⽣成Verilog代码及测试⽤的⼊⼝⽤到的命令:
cd emulator
make CONFIG=DefaultConfig
其中CONFIG=后⾯接的是在src/main/scala/system/Configs.scala写好的类名。
若编译没有错误,则会⽣成以下⽂件和⽂件夹:
在这⾥插⼊图⽚描述
generated-src⽂件夹包括⽣成的Verilog⽂件和⼀些测试⽤的⽂件,verilator⽂件夹包含仿真⼯具verilator的源码和安装⽂件。
emulator-freechips.rocketchip.system-DefaultConfig是可执⾏⽂件,是测试程序的⼊⼝。
图中圈着的⽂件夹是测试进⾏的环境,.v⽂件就是⽣成的rocket-chip的Verilog代码。
在这⾥插⼊图⽚描述
rocket-chip generator仿真C或C++程序
1. 使⽤risc-v⼯具链编译仿真
写好的⼀个测试的C或C++程序如下:
使⽤命令编译测试程序:
riscv64-unknown-elf-gcc helloworld.c -o helloworld
然后将⽣成的helloworld可执⾏⽂件放到emulator⼯作⽬录,再在emulator⼯作⽬录下执⾏命令:
./emulator-freechips.rocketchip.system-DefaultConfig pk helloworld
等待⼏分钟(具体等待时间取决于程序的⼤⼩)后,终端输出“Hello World”
2.利⽤rocket的⽅法如下(⽐之前的跑的更快,⽽且能看波形)
在rocket-chip/riscv-tools/riscv-tests/benchmarks中新建测试程序的⽂件夹helloworld,并在其中写好⼀个测试程序helloworld:
修改在rocket-chip/riscv-tools/riscv-tests/benchmarks中的Makefile,修改其中的bmarks变量,使其新值为新建的⽂件夹名字helloworld:
退出到rocket-chip/riscv-tools/riscv-tests/benchmarks执⾏命令make,得到.riscv可执⾏⽂件:
将.riscv⽂件移到rocket-chip/emulator⽂件夹中:
执⾏命令:
./emulator-freechips.rocketchip.system-DefaultConfig helloworld.riscv
等待少于⼀分钟的时间,得到输出:
执⾏命令:
./emulator-freechips.rocketchip.system-DefaultConfig +max-cycles=100000000 +verbose helloworld.riscv 2> helloworld.riscv.out
得到指令执⾏过程信息:
执⾏命令:
./emulator-freechips.rocketchip.system-DefaultConfig-debug +max-cycles=100000000 --vcd=helloworld.riscv.vcd helloworld.riscv
得到.vcd波形⽂件:
双击打开即可看到波形:
附录:Chisel3 & Scala & Rocket-chip verilog的⽣成
Scala是⼀门多范式的编程语⾔,⼀种类似java的编程语⾔,设计初衷是实现可伸缩的语⾔、并集成⾯向对象编程和函数式编程的各种特性[1]。
Chisel(Constructing Hardware In a Scala Embedded Language)是⼀种嵌⼊在⾼阶编程语⾔ Scala 中⽤来构造硬件的语⾔。
Chisel实际上只是⼀组特殊的⽤Scala 事先定义的类、对象和使⽤惯例,所以写⼀份Chisel程序的时候,你实际上在写⼀份Scala程序[2]。
Rocket Chip is an open-source Sysem-on-Chip design generator that emits synthesizable RTL. It leverages the Chisel hardware construction language to compose a library of sophisticated generators for cores, caches, and interconnects into an integrated SoC[3].
由上⾯描述,应该可以知道,Rocket Chip是⼀个开源的SOC⽣成器,可以根据⾃⼰的配置⽣成不同的SOC(RTL),⽽Rocket Chip是基于Chisel完成的,最后Chisel是在Scala中定义的特殊类和对象,因此修改Rocket Chip的源代码就是修改Scala代码,利⽤Chisel编译出的⽂件为*.fir,要将*.fir转换为verilog RTL还需要firrtl这个⼯具。
Rocket Chip整个项⽬的Scala编译都基于sbt的,⽽sbt是基于java的,因此要⽣成Rocket-chip RTL,要先安装java,sbt,chisel3和firrtl。
注意Rocket-chip RTL的⽣成不会⽤到⼯具链,需要编译⼯具链时才需要设置环境变量。
Rocket-chip verilog RTL⽣成步骤:
1、克隆项⽬:
sudo apt-get install default-jdk
3、安装sbt,安装sbt过程中可能因为⽹速或链接的问题会出现下载失败的现象,多试⼏次就好:cd rocket-chip sbt
直到弹出这样的提⽰就证明成功了,然后输⼊exit退出:
sbt:rocketchip>
5、编译&安装chisel3:
cd rocket-chip/chisel3 sbt
直到弹出这样的提⽰就证明成功了,然后输⼊exit退出:
sbt:chisel3>
6、编译&安装firrtl:
cd rocket-chip/firrtl sbt
直到弹出这样的提⽰就证明成功了,然后输⼊exit退出:
sbt:firrtl>
7、⽣成rocket-chip verilog RTL
cd rocket-chip/vsim make verilog CONFIG=DefaultSmallConfig
漫长等待后,RTL⽣成
$cd rocket-chip/vsim/generated-src
这个⽬录下有很多刚⽣成的东西,下⾯再对这个⽬录⽣成的⽂件进⾏说明。
⽣成⽂件的说明:
JSON(JavaScript Object Notation, JS 对象简谱) 是⼀种轻量级的数据交换格式⽂件说明RISC-V编译环境搭建
1. JTAG调试器设置
将JTAG调试器连接PC,并断开主机连接将其连接到UBUNTU虚拟机,运⾏
lsusb
应该有以下这个设备:
Bus 002 Device 010: ID 0403:6010 Future Technology Devices International, Ltd FT2232C Dual USB-UART/FIFO IC 设置udev rules,使JTAG调试器可以被plugdev group访问
sudo gedit /etc/udev/rules.d/99-vmware-scsi-udev.rules
在⾥⾯添加
ATTR{idVendor}=="0403", ATTR{idProduct}=="6010", MODE="660", GROUP="plugdev"
使⽤如下命令查看该USB设备是否属于plugdev group
ls -l / /dev/ttyUSB1
2. 将⽤户名添加到plugdev group中
whoami
sudo usermod -a -G plugdev username
确认⾃⼰的⽤户名是否属于plugdev group
groups
将gnu-mcu-eclipse-openocd-0.10.0-8-20180724-1118-centos64.tgz放到~/根⽬录下,并解压
cd ~/
tar -xzvf gnu-mcu-eclipse-openocd-0.10.0-8-20180724-1118-centos64.tgz
cd ~/e200_opensource/sirv-e-sdk/
mkdir -p work/build/opencd/prefix
cd work/build/opencd/prefix/
ln -s ~/gnu-mcu-eclipse/openocd/0.10.0-8-20180724-1118/bin/ bin
cd ~/e200_opensource/sirv-e-sdk/
mkdir -p work/build/riscv-gnu-toolchain/risc32-unknown-elf/prefix/
cd work/build/riscv-gnu-toolchain/risc32-unknown-elf/prefix/
ln -s ~/gnu-mcu-eclipse/riscv-none-gcc/7.2.0-2-20180111-2230/bin/ bin
3. 编译demo_gpio程序,命令如下:
cd ~/e200_opensource/sirv-e-sdk/
make software PROGRAM=demo_gpio BOARD=sirv-e203-arty
如何建⽴⾃⼰的RISC-V编译环境?
1.RISC-V编译环境框架
这是我RISC-V编译环境的架构:
build case common toolchain
2.2 project:这个⽬录就是放你的项⽬代码的。
每个项⽬建⽴⼀个⽬录。
在这个例⼦中,我放的是test⽬录,test的源代码如下(修改于/riscv-tests/benchmarks/vvadd):
2.3 common:这个⽬录⽐较重要,⽽且改动的地⽅⽐较多。
2.3.1 encoding.h:这个⽬录不解释,就是RISC-V各重要CSR寄存器的定义。
2.3.2 program.ld:这个⽂件是修改于/riscv-tests/benchmarks/common/test.ld。
2.3.3 program.S:这个⽂件改动⽐较⼤(修改于/riscv-tests/benchmarks/common/crt.S),这个⽂件改动需要注意以下⼏点:
1)扩展名必须为⼤写的S,⼤写的S可以使gcc⾃动识别汇编程序中的C预处理命令,像#include、#define、#ifdef、 #endif等,也就是说,使⽤gcc进⾏编译,你可以在汇编程序中使⽤C的预处理命令。
2)因为我⽣成的rocket-chip是不使⽤浮点的,不使⽤虚拟内存,不使⽤ROCC的,所以很多内容我直接删改了,⽽且栈和异常⼊⼝都是根据我⽣成的rocket-chip来设定的,⼤家可以根据⾃⼰的情况进⾏修改。
2.4 bulid:这个⽬录最主要的是Makefile脚本,⽤于调⽤⼯具链编译project。
我只贴部分代码,是⽣成elf的代码,⽣成bin、hex和dump的⽅法⼤家参考/riscv-tests/benchmarks/Makefile。
部分代码:
Processing math: 0%。