首页IT科技吃蒜的好处与功效(chisel学习笔记——基本类型)

吃蒜的好处与功效(chisel学习笔记——基本类型)

时间2025-06-18 22:29:05分类IT科技浏览4558
导读:Chisel学习笔记(二)——基本类型 因为是对着chisel book学的,这篇实际上是加上我的理解的chisel book的翻译...

Chisel学习笔记(二)——基本类型

因为是对着chisel book学的            ,这篇实际上是加上我的理解的chisel book的翻译

1.信号类型与常量

Chisel提供了三种基本的类型来描述信号            、寄存器                  、组合逻辑:

Bits SInt UInt

此外                   ,还定义了逻辑类型Bool            。

1.1类型定义

一个Chisel类型的定义有两部分:位宽与类型

比如看下面的例子:

Bits(7.W) SInt(8.W) UInt(9.W)

分别定义了7bits的Bits类型      ,8bits的有符号数         ,9bits的无符号数

1.2 常量定义

而一个Chisel常量类型的定义则有三部分:位宽       、类型和值

比如看下面的例子:

-3.S(4.W)

​ 这个定义代表一个4bits的有符号数3                   ,其中-3         、4都是Scala原生的整型         ,而通过.S                  、.W转换为Chisel定义的有符号数与宽度类型

​ 对于上面的例子应该这样理解      ,首先4.W将Scala整型4转换为Chisel width                   ,然后作为参数传入.S构成Chisel四位有符号数类型            ,然后把Scala整型-3转换为Chisel四位有符号数-3                  。

对于常量的定义   ,还可以使用其它的进制(16          、8      、2)                   ,这种情况下应该用Scala的字符串类型来表达               ,如:

"hff".U "o377".U "b1111_1111".U

都代表十进制的255

2. 组合逻辑

​ 首先有必要介绍Scala的一个特性——类型推断,类似C++的auto                ,对应的关键字为val       。这个特性使得我们可以不用像Verilog一样                   ,对每一个变量显式声明它的类型                  、位宽(位宽实际上作为Bits             、SInt   、UInt类型的一项属性存在)         。

​ 先看一个例子:

val logic = a & b | c

上面的代码描述了下面这样一个电路:

​ 代码中   ,logic的类型为val            ,如前述                   ,这不是一个实际的类型      ,只是表示logic是一个变量         ,而logic的变量由Scala推断得出                  。

​ 另外                   ,还可以先将一个变量定义为Wire         ,然后再用一种持续赋值的方法来进行“连接            ”:

val w = Wire(UInt()) w := a & b

​ 可以通过类似下标访问的方法来提取某一位或一个区间:

val bit31 = x(31) val bit0to7 = x(7, 0)

​ 还可以进行拼接:

val word = bits1 ## bits2

​ 下面两张表介绍了Chisel中定义的一些硬件算子:

Operator Description Data Types *                  、/                、% 乘、除               、取模 UInt                   、SInt +    、- 加            、减 UInt                  、SInt ===       、=/= 等于         、不等于 UInt                  、SInt      ,返回Bool >          、>=      、<                  、<= 大于             、不小于   、小于                  、不大于 UInt                、SInt                   ,返回Bool <<、>> 左移               、右移(UInt逻辑移位                   、SInt算术移位) UInt    、SInt ~ 非 UInt            、SInt                  、Bool &       、|         、^ 与                  、或          、非 UInt      、SInt                  、Bool ! 逻辑非 Bool &&             、|| 逻辑与   、或 Bool Function Description Data Types v.andR                  、v.orR                、v.xorR AND、OR               、XOR reduction UInt                   、SInt    、returns Bool v(n) 提取1bit UInt            、SInt v(end, start) 提取区间 UInt                  、SInt Fill(n, v) 将v复制n遍 UInt       、SInt a ## b 拼接 UInt         、SInt Cat(a, b, ...) 拼接 UInt                  、SInt Mux(sel, a, b) 多路选择器 sel:Bool            ,a          、b:任何相同的Chisel类

3. 寄存器

​ Chisel提供的寄存器接口是高度抽象和封装的          。寄存器的时钟被连接到一个全局时钟   ,复位被连接到一个全局同步复位                   ,只留下了输入      、输出两个接口供使用      。虽然自由度变低了               ,但使用也相对简化了,实际上只有初始化                  、连接输入             、连接输出三件事要做:

val reg = RegInit(0.U(8.W)) reg := d val q = reg

或者也可以这样写:

val reg = RegNext(d, 0.U(8.W)) val q = reg

4. Bundle和Vec

Bundle是异构的类型集合                ,可以通过继承Bundle类来定义:

class MyBundle extends Bundle{ val d1 = UInt(8.W) val d2 = Bool() }

然后在使用前进行声明                   ,Bundle内数据的访问实际上就是对类属性的访问:

val mb = Wire(new MyBundle()) mb.d1 := 2.U mb.d2 := true.B

Vec是同构的类型集合   ,通过Vec类定义            ,下标访问:

val vec = Wire(Vec(3, UInt(4.W))) vec(0) := 1.U vec(1) := 2.U vec(2) := 3.U val q = vec(0)

还可以通过初始化函数定义                   ,这种方法直接产生Wire      ,不需要再转换:

val d = 3.U(4.W) val vec = VecInit(1.U(4.W), 2.U, d)

Vec默认是一组Wire         ,但也有RegFile型的:

val rf = Reg(Vec(32, 0.U(32.W))) val rf = RegInit(VecInit(Seq.fill(32)(0.U(32.W))))

Bundle与Vec可以互相包含:

class VecBundle extends Bundle{ val d1 = UInt(8.W) val v1 = Vec(3, UInt(4.W)) } BundleVec = Wire(Vec(3, new VecBundle()))

另外                   ,Bundle与Vec还有一个重要的用途                  。Chisel3不支持对一个变量部分赋值         ,比如说这样写是会报错的:

val dat = Wire(UInt(8.W)) dat(7:4) := "h1".U(4.W) dat(3:0) := "h2".U(4.W)

作为替代      ,可以用Vec和Bundle实现分段

5. Wire   、Reg                  、IO

​ 上面提到的各种类型支持了多样的设计                   ,但许多还不能直接对应到硬件结构             。Wire                、Reg、IO分别对应了连线            ,寄存器   ,输入输出端口   。组合逻辑的信号需要用Wire显式声明                   ,Reg与前述是一样的               ,IO是输入输出端口                  。

Wire与IO的用法与Reg类似:

val w = Wire(UInt(8.W)) w := 8.U(8.W) val v = WireDefault(8.U(8.W))

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
win10系统待机后无法唤醒(win10待机唤醒桌面空白怎么办) cvpr期刊(CVPR 2022 结果出炉,最全论文下载及分类汇总(更新中))