Chisel 函数式 examples

学习 Chisel 的高级用法,需要先了解 Scala 的函数式编程,这里记录一些 Chisel 的函数式用法。


Vector map zip case

1
2
val tagCheckVec = Wire(Vec(wayAmount, Bool()))
tagCheckVec := (tagData.map( _ === tag) zip valid(index)).map{case (tagMatch, isValid) => tagMatch && isValid}

对一个名为 tagCheckVec 的 Vec 对象进行赋值操作。这个 Vec 对象的元素类型是 Bool,长度与 tagData 相同。tagData 是另一个 Vec 对象,元素类型为 UInt,表示缓存中每个条目的标记。
在这段代码中,首先对 tagData 中的每个元素都执行了一个等于操作,判断它是否等于 tag。这个 tag 是一个 UInt 类型的输入参数,表示要查找的标记。
这个等于操作返回的结果是一个 Bool 类型的 Vec 对象,长度与 tagData 相同。
接着,将这个 Vec 对象与 valid(index)进行 zip 操作,其中 valid 是一个 Bool 类型的 Vec 对象,表示缓存中每个条目是否有效,index 是一个 UInt 类型的输入参数,表示要查找的条目的索引。
zip 操作返回的结果是一个元素类型为(T, U)的 Vec 对象,其中 T 是 tagData 中每个元素与 tag 进行等于操作的结果,U 是 valid 中对应元素。
最后,对这个 Vec 对象中的每个元素都执行了一个逻辑与操作,将结果赋值给 tagCheckVec。这个操作的结果是一个 Bool 类型的 Vec 对象,表示缓存中每个条目的标记是否与输入参数 tag 相同并且该条目有效。


Vector indexWhere contains

1
2
hitWay := tagCheckVec.indexWhere(tagMatchAndValid => tagMatchAndValid  === true.B)
isHit := tagCheckVec.contains(true.B)

通过 indexWhere 方法获得符合条件的第一个元素的索引,通过 contains 方法判断是否存在符合条件的元素。


Decoupled

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Producer extends Module {
val io = IO(new Bundle {
val out = Decoupled(UInt(32.W))
})

val count = RegInit(0.U(32.W))

io.out.bits := count
io.out.valid := true.B

when(io.out.ready) {
count := count + 1.U
}
}

class Consumer extends Module {
val io = IO(new Bundle {
val in = Flipped(Decoupled(UInt(32.W)))
})

when(io.in.valid) {
printf("Received data: %d\n", io.in.bits)
}

io.in.ready := true.B
}

Decoupled 包括两个信号,valid 和 ready,分别表示数据有效和数据可用。当 valid 为 true 时,数据可用,当 ready 为 true 时,数据有效。当 valid 和 ready 同时为 true 时(也就是 fire 时),数据传输完成。


Vec contains

1
2
3
4
5
/** judge whether op is to load data from memory */
def opIsLoad(op: UInt): Bool = {
require(op.getWidth == opLen)
VecInit(MEM_LB, MEM_LBU, MEM_LH, MEM_LHU, MEM_LW, MEM_LWL, MEM_LWR, MEM_LL).contains(op)
}

判断指令属于哪一类指令


Vec map foreach

1
2
3
4
5
6
7
8
io.slaves
.map(_.ar)
.foreach(ar => {
ar.ready := false.B
})
```

通过map foreach减少for循环