Skip to main content

Chisel菜鸡学习心得

还是下决心学chisel了,我跟着riscv-mini的核来进行学习,这篇博客主要记录一些过程中遇到的问题和解决或者心得

Type

第一个搞清楚的概念就是chisel的type了,也是这个促使我写的博客

chisel的type不像其他编程语言的type那么直观,因为他是“二维”的

chisel的type包括硬件结构硬件类型

  • 硬件类型包括UInt,SInt
  • 硬件结构包括Wire,Reg,Mem甚至Module等等

用English就是chisel type和chisel component

我一开始没有分清楚所以很迷惑,For example:

val a = 3.U + 4.U

这里的a的硬件结构或者节点是Wire或者Output…a的硬件类型是UInt,可以看出,表达式本身帮助我们推断出了他的硬件结构

之后还有两个常用type:Bundle和Vec

Bundle是类似c语言的struct一样的作用,将不同的硬件类型结合起来形成一个“新的硬件类型”,但是Bundle本身并没有映射到具体的硬件结构上面,所以,我们需要这样初始化Bundle:

val a = IO(new Mybundle)

才能将其映射到一个具体的硬件结构

Vec我还不太了解,但是初步了解是一个类似数组的东西,是将一系列的硬件结构组合起来,并且可以索引

还有一种类型叫做probe

但是网上资料甚少,似乎是不破坏电路结构但是存在的一个io?搞不太懂

我查询了一下verilog的xmr

1.8. HDL代码中的跨模块引用(XMR) (intel.cn)

然后我在某ysyx助教的博客中的slide找到了具体的用法eminblog.cc/slides/chisel/

BlackBox

由于我需要使用Dpi-C功能,我需要使用sv来编写一些代码,所以需要使用chisel的blackbox功能

这个简单来说就是extends BlackBox而不是Module,这样它例化的时候就不会带上一些奇怪的东西(比如io),至于addPath,addResource这些方法我感觉没什么用,他是把verilog文件复制到目标文件夹,其实只要把所有目录里面所有的verilog文件找出来传给verilator就行,只要确保生成的verilog例化时的语法正确就行

Mux

这个也是一个经常会使用的东西,chisel提供了很多类似的“函数”,具体见Muxes and Input Selection | Chisel (chisel-lang.org),但是还有一个叫做ListLookup不知道为什么文档没有写,但是API是可以看到的chisel 6.3.0 – chisel3.util.ListLookup (chisel-lang.org)

基本上ysyx讲义上提供的模版就是MuxLookup,基本上就使用mux就可以避免所有行为建模了吧

Reg

如果说Mux是组合逻辑的神器,那reg就是时序逻辑不可缺少的一部分,chisel提供了很多实现触发器的模版,随便找一个文章学习一下Chisel Registers Tutorial – Learn FPGA Easily,不过最好还是看官网比较好点

寄存器文件一般使用Mem来例化

Connect operator

似乎官网并不建议使用<>(至于两者的区别,似乎:<>=检查的更严格)

主要就是五种

  • :=
  • :>=
  • :<=
  • :<>=
  • :#=

具体见官网,我暂时还没搞太清楚(上面那个wordpress会自动给我整成大于等于,实际上是分开的)

Connectable Operators | Chisel (chisel-lang.org)

今天忽然发现一个问题,<>这个运算符(也就是:<>=运算符),在连接同一级别的模块的时候似乎是连接input到output,output到input,但是,在连接父模块与子模块时,似乎是连接input到input,output到output,如图所示

并且连线的时候会有一个比较绕但是不复杂的东西,你连接到外部模块是要连接到本模块的output,再在更上层模块连接到外部模块的input,并从本模块的input获取数据,连接到内部模块要连接到内部模块的input,并从内部模块的output获取数据,其实就是上图

他这个连接的话如果是两个不同的bundle是不能直接连接的,即使他们的field是一样的,但是,似乎可以通过一些办法进行连接

chisel究竟还有多少我不知道的东西

SVA

SerializableModule

将模块extend这个module可以使得模块可以被序列化,他仅仅依赖(也只能依赖)一个 SerializableModuleParameter的参数,这两个如果被提供给一个SerializableModuleGenerator,那这个generator就可以被upickle write变成一个json,还可以被upickle read重新变成一个generator,也就是Serializable的含义,SerializableModuleGenerator有一个module方法,可以将他变成一个普通的module,从而被使用,至于为什么需要这个,实际上是可以把elaborate的粒度变成模块级,而不是整个设计级,详情请参考官方文档和示例:https://www.chisel-lang.org/docs/cookbooks/serialization

chisel上游还有一个新的api,叫做SerializableModuleElaborator,本质上是对generator的一个包裹

这个特性我会在我重构我riscv-core时使用

Object Model

文档看不懂,暂时跳过吧,不过看起来可能也用不上,他作用的点在后段从IR中提取相关信息

DataView

就是把一个Data看成viewAs为另一个Data类型,或者把一个non-Data类型看成一个Data类型,具体可以看文档,讲得非常清楚https://www.chisel-lang.org/docs/explanations/dataview

Layer

具体请看文档,感觉还挺好用的,比如verilator不支持SVA,我只需要不包括这层生成的文件就可以了

但是感觉多用于验证部分和作为一些DEBUG手段(像是c的#ifdef DEBUG …. #endif)

Decoder

很早以前听说过这个东西,但是之前用LIstLookup已经写好了,没有用武之地了,现在正好要重写了,就打算学习一下

我的理解就是decoder是把一个数据的pattern,根据field的gentable生成真值表
所以就首先需要pattern,pattern在idu中就是指令的信号,有一个rvdecodedb的东西,可以根据rv的规范自动给你生成所有指令的pattern
然后就是field,每一个field就是一个输出,也就是一个输出信号