在学习SpinalHDL官方手册的时候,发现了复合类型Vec里面有这样一个函数
从解释可以看出,这个函数的作用是平衡减少功能,尽量减少所产生的电路深度。也就是说在
在硬件描述语言(HDL)中,我们通常使用树结构来表示多个信号或数据的连接。然而,如果树结构不平衡,可能会导致某些信号的传播路径较长,从而影响电路的延迟和性能。
怎么理解呢?可以从一个小例子来说明
假如我们要实现一个
那么则有以下
import spinal.core._ class DemoReduceBalancedTree extends Component{ val vec1 = in Vec(UInt(8 bits),4) // // val a = vec1.reduce(_ + _) // 实现对vec1中所有元素求和 // 作为输出 val b = vec1.reduce(_ + _).asOutput // 方便vivado中观看电路概图 } object DemoReduceBalancedTree extends App{ SpinalConfig(targetDirectory = "rtl").generateVerilog(new DemoReduceBalancedTree) }
经过编译,上述代码生成了下面的
module DemoReduceBalancedTree ( input [7:0] vec1_0, input [7:0] vec1_1, input [7:0] vec1_2, input [7:0] vec1_3, output [7:0] b ); wire [7:0] _zz_b; wire [7:0] _zz_b_1; assign _zz_b = (_zz_b_1 + vec1_2); assign _zz_b_1 = (vec1_0 + vec1_1); assign b = (_zz_b + vec1_3); endmodule
我们把改代码导入到
可以看到,实现了四个元素的和使用了三个加法器,可以对电路进行优化,即
val c = vec1.reduceBalancedTree(_ + _).asOutput
可以看到生成的
module DemoReduceBalancedTree ( input [7:0] vec1_0, input [7:0] vec1_1, input [7:0] vec1_2, input [7:0] vec1_3, output [7:0] c ); wire [7:0] _zz_c; wire [7:0] _zz_c_1; assign _zz_c = (vec1_0 + vec1_1); assign _zz_c_1 = (vec1_2 + vec1_3); assign c = (_zz_c + _zz_c_1); endmodule
看到电路图更加的清晰
总的来说它可以创建一个平衡的树结构,以优化电路的性能和资源利用。
当然,这个函数还有一些其他的用法,比如说实现两个集合元素的翻转
vec1 | 0 | 1 | 2 | 3 |
---|---|---|---|---|
vec2 | 3 | 2 | 1 | 0 |
val vec1 = in Vec(UInt(8 bits),4) val vec2 = out Vec(UInt(8 bits),4) vec2.assignFromBits(vec1.reverse.reduceBalancedTree(_ @@ _).asBits)
-
vec1.reverse :这个操作对vec1 进行反转。例如,如果vec1 的初始值是[a, b, c, d] ,那么反转后的结果就是[d, c, b, a] 。 -
reduceBalancedTree(_ @@ _) :这个操作将反转后的vec1 中的元素进行二叉树归约。使用@@ 运算符将两个元素连接起来,直到最终得到一个单一的元素。例如,对于[d, c, b, a] ,进行二叉树归约的过程如下:cssCopy code [d, c, b, a] -> [(d @@ c), (b @@ a)] -> [dcba]
归约过程中,每次将两个元素连接成一个新元素,直到最终得到一个包含所有元素的向量。
-
asBits :这个操作将归约后的结果转换为Bits 类型。Bits 是Chisel中表示位向量的类型。 -
vec2.assignFromBits(...) :这个操作将位向量转换后的结果赋值给vec2 。这意味着vec2 的每个元素将被设置为归约后的结果中对应的位。
综上所述,这段代码的作用是将
参考资料:1. SpinalHDL教程