type
status
date
slug
summary
tags
category
icon
password
💡
该文档适用于 chisel3.x 版本,由于 chisel 6 相对于之前的版本有较大升级,后面会更新一下仓库内容,重写部分构建代码。
 
Chisel 环境的搭建已经有很多教程我就不多赘述了,主要是有一个外网环境的服务器或者连接代理的终端。本文主要描述如何搭建使用 mill 工具和 verilator 仿真器进行电路设计和仿真的工程框架,将以一个 38 译码器为例讲解该框架。
工程框架我也建立了一个 Github 仓库,如何运行示例,以及对工程的基本操作也在仓库 Readme 中写明,欢迎交流学习。

框架结构

因为使用 mill 作为工具构建 Chisel 工程,所以在项目结构上就要遵循 mill 的规则。建立如下结构的工程目录:
Chisel project template
Chisel project template
框架中对于 Chisel 工程来说重要的是 build.sc 和 src 文件夹。build.sc 文件是 mill 构建工程的配置文件,src 目录则存放 Chisel 工程的源代码。而 sim_c 文件夹中则是使用 verilator 进行仿真的仿真源代码。Makefile 可以为工程提供自动化编译运行的便利。
接下来将从 Chisel 部分和 verilator 部分两方面介绍工程框架

Chisel 部分

build.sc

在该文件中主要是添加一些构建选项和依赖,在构建时,mill 会联网下载指定的依赖,存放于 out 文件夹。对于一个简单的 Chisel 工程来说,并不需要复杂的依赖,而且由于我们使用 verilator 进行设计仿真,所以也暂时不需要引入 chiseltest 相关的依赖。一个简单的 build.sc 的示例如下所示:
比较需要注意的是,millSourcePath 这个变量,必须是 src 目录的位置,mill 工具会根据这一变量的值去解析当前工程,如果设置错误,则会使 mill 不能正确的解析工程,导致构建 Chisel 工程的过程中出现 No main class specified or found 等错误。

src

一般的 Chisel 工程中,源文件目录都分为 main 和 test 两部分。其中 main 部分放置电路的实现部分,test 放置一些使用 Chiseltest 完成的测试用例。因为本框架不使用 Chiseltest 功能,所以只是建立了一个空的 test 目录。另外,之所以不是直接在 main 文件夹下编写 top.scala 而是又建立了 scala 文件夹,是由于在 Chisel 中允许以文件的形式插入 Verilog 代码段,而这些 Verilog 代码会放置在 src/main/resource 文件夹下。
所以如果要实现自己的设计,修改 src/main/scala 下的 scala 文件即可。本工程实现了一个 38 译码器,并在顶层模块对其进行了实例化和端口的连接。
不熟悉 Chisel 实现的同志可以阅读 Chisel 的官方 doc,或者我翻译的版本
{% fold 点击展开译码器实现代码 %}
在编写完以上内容后一个 Chisel 工程就已经建立完成了,可以使用 mill top.runMain top.topMain 命令构建工程,这会在当前目录生成 Verilog 代码。-td 参数可以指定 mill 将 verilog 代码生成到何处。第二个参数中的 .topMain 与 top.scala 中的 App 对象一致即可。

verilator 部分

本工程使用 Verilator 进行电路设计的仿真。仿真文件存放在 sim_c 目录中。
将所有仿真相关的内容放在 sim.cc 中实现,并通过 sim.h 提供必要的接口。

仿真函数介绍

  • sim_init(): 初始化仿真,初始化使用的函数指针,如果需要创建 logs 文件夹,打开波形文件准备记录数据。
  • sim_exit(): 与 sim_init 对应,释放相关指针,关闭波形文件。
  • reset(int n): 拉高复位值 n 个周期。
  • single_cycle(): 仿真一个周期。
  • sim_main(int argc, char *argv[]): 仿真主循环。
sim_main() 中,因为译码器是单纯的组合逻辑,所以没有使用 single_cycle() 函数推进仿真。而是编写了一个循环遍历 38 译码器的输入,之后跳出循环结束仿真。在每一次修改完端口的值后都要记得执行 top->eval() 函数,不然电路的值不会更新。其次在 single_cycle() 中写出了绘制波形的代码,即在每次执行 top->eval() 之后,通过 tfp->dump(contextp->time()); 一个时间单位的波形。
写到这里就可以使用 verilator 进行编译仿真了:
不熟悉 verilator 命令和仿真程序编写的的同志可以看看 verilator 的官方文档
完成编译后,会将 Chisel 部分生成的 Verilog 代码和 仿真源程序编译成可执行文件,./build/top 就可以运行仿真了。

Makefile 实现编译仿真的自动化

为了使上面的构建和仿真的命令变得容易,我们可以将其写入 Makefile 文件来简化编译仿真流程。
我们在 Makefile 中构建了每一步单独的目标(verilog、sim、run)和总体的构建运行的目标(srun)。使用 make -n 可以使我们清晰的看到每一个目标运行了什么命令但不真正执行。对 Makefile 不熟悉的同志可以查看这篇教程
至此对于该工程模板的介绍就完成了,在编写自己的工程时只需要修改 src 中的 scala 文件以及 sim_main 中的仿真步骤,然后编译运行即可。
RISC-V Spike 代码分析Chisel 官方文档翻译
Loading...