本实验所有代码开源在:https://github.com/littlebear0729/chisel-matrix-multiplication
实验目的
使用基于Scala的Chisel语言设计实现矩阵乘法,并评估不同的实现方式所需的时钟周期数。
实验内容
本实验分别使用Chisel语言设计了三种矩阵乘法的实现,分别是:
MatMul1*.scala
:组合电路,单周期实现MatMul2*.scala
:时序电路,多周期实现MatMul3*.scala
:时序电路,多周期实现,流水线优化
对于每一种实现均有三个文件,分别是:
MatMul1.scala
:负责使用不同方法实现电路设计MatMul1IO.scala
:负责处理电路输入和输出MatMul1Tester.scala
:负责对实现的电路进行测试
本实验对三种电路实现方式设计了同一测试数据,期望比较相同测试数据对不同的电路设计所需时钟周期数进行比较。
A矩阵:3 * 2
1 | 0 1 |
B矩阵:2 * 4
1 | 0 1 2 3 |
期望输出矩阵:3 * 4
1 | 4 5 6 7 |
实验步骤与结果
运行测试
分别运行
sbt "runMain madd.MatrixMul(1-3)Tester"
,观察其输出。运行结果分别如下:
MatrixMul1Tester.scala
1
2
3
4
5
6
7
8
9
10[info] running madd.MatrixMul1Tester
Elaborating design...
Done elaborating.
End of dependency graph
Circuit state created
[info] [0.000] SEED 1653635420028
test MatrixMul1 Success: 12 tests passed in 5 cycles taking 0.040479 seconds
[info] [0.005] RAN 0 CYCLES PASSED
[success] Total time: 9 s, completed May 27, 2022 3:10:21 PMMatrixMul2Tester.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21[info] running madd.MatrixMul2Tester
Elaborating design...
Done elaborating.
End of dependency graph
Circuit state created
[info] [0.001] SEED 1653635477340
[0] state: 1
[1] state: 0
[2] state: 1
[3] state: 0
[4] state: 1
<中间省略较多0和1...>
[43] state: 0
[44] state: 1
[45] state: 0
[46] state: 1
[47] state: 2
test MatrixMul2 Success: 12 tests passed in 53 cycles taking 0.079975 seconds
[info] [0.051] RAN 48 CYCLES PASSED
[success] Total time: 5 s, completed May 27, 2022 3:11:18 PMMatrixMul3Tester.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17[info] running madd.MatrixMul3Tester
Elaborating design...
Done elaborating.
End of dependency graph
Circuit state created
[info] [0.000] SEED 1653635549165
[0] io.in.fire(): 1, regA: 0, regB: 0, regLoadEnabled: 1, regComputeEnabled: 1, regStoreEnabled: 0, regOut: Vec(527764349, -549288007, -1671823787, -1119473207, 756909588, 393113626, 1704158961, 1173153012, 594757044, -1141106840, 1283530375, 1943948619), i: 0, j: 0, io.out.fire(): 0
[1] io.in.fire(): 1, regA: 1, regB: 4, regLoadEnabled: 1, regComputeEnabled: 1, regStoreEnabled: 0, regOut: Vec(0, -549288007, -1671823787, -1119473207, 756909588, 393113626, 1704158961, 1173153012, 594757044, -1141106840, 1283530375, 1943948619), i: 0, j: 0, io.out.fire(): 0
[2] io.in.fire(): 1, regA: 0, regB: 1, regLoadEnabled: 1, regComputeEnabled: 1, regStoreEnabled: 0, regOut: Vec(4, -549288007, -1671823787, -1119473207, 756909588, 393113626, 1704158961, 1173153012, 594757044, -1141106840, 1283530375, 1943948619), i: 0, j: 1, io.out.fire(): 0
<中间省略较多输出...>
[22] io.in.fire(): 1, regA: 4, regB: 3, regLoadEnabled: 1, regComputeEnabled: 1, regStoreEnabled: 0, regOut: Vec(4, 5, 6, 7, 12, 17, 22, 27, 20, 29, 38, 1943948619), i: 2, j: 3, io.out.fire(): 0
[23] io.in.fire(): 1, regA: 5, regB: 7, regLoadEnabled: 1, regComputeEnabled: 1, regStoreEnabled: 0, regOut: Vec(4, 5, 6, 7, 12, 17, 22, 27, 20, 29, 38, 12), i: 2, j: 3, io.out.fire(): 0
[24] io.in.fire(): 0, regA: 5, regB: 7, regLoadEnabled: 0, regComputeEnabled: 0, regStoreEnabled: 1, regOut: Vec(4, 5, 6, 7, 12, 17, 22, 27, 20, 29, 38, 47), i: 0, j: 0, io.out.fire(): 1
test MatrixMul3 Success: 12 tests passed in 30 cycles taking 0.072125 seconds
[info] [0.064] RAN 25 CYCLES PASSED
[success] Total time: 3 s, completed May 27, 2022 3:12:30 PM记录不同电路使用时钟周期数
通过关注输出倒数第二行的信息,可知这三种电路设计方式分别运行所有时钟周期0次、48次、与25次。
计算加速比
针对于目前的测试案例,输出为3*4的矩阵,加速比为$48 / 25=1.92$。
可以推算,若样例为8*8的输出矩阵,未使用流水线优化的时序电路时钟周期为1024次,使用流水线技术优化的时序电路周期为513次。加速比为$1024 / 513$,约为$1.9961$。
可知使用流水线优化后可减少约一半的时钟周期。
小结
由于对Scala语言的不熟悉,没有完成8 * 8矩阵的随机测试。同时,512 * 512矩阵的分块计算也没有完成,略显遗憾。
对于流水线优化方法,由于可以将load与compute结合在一个时钟周期内,最后进行store处理。所以总共可以减少约一半的时钟周期。
心得与建议
通过本实验我初步了解了如何使用Chisel语言进行电路设计,了解组合电路与时序电路的特点,以及在每一个时钟周期内电路所做的工作。
由于没有数字逻辑和硬件编程的基础,上手速度还是略慢。如果时间充裕,可以考虑将8 * 8的随机矩阵和512 * 512的分块实现。