SpinalHDL中的ReduceBalancedTree()函数

在学习SpinalHDL官方手册的时候,发现了复合类型Vec里面有这样一个函数

在这里插入图片描述

从解释可以看出,这个函数的作用是平衡减少功能,尽量减少所产生的电路深度。也就是说在 SpinalHDL 中,reduceBalancedTree 是一个用于执行平衡树归约操作的函数。它可以将一个包含多个输入信号的列表归约为一个输出信号。

在硬件描述语言(HDL)中,我们通常使用树结构来表示多个信号或数据的连接。然而,如果树结构不平衡,可能会导致某些信号的传播路径较长,从而影响电路的延迟和性能。

reduceBalancedTree函数通过重新组织树结构,将信号的传播路径尽可能均匀地分布在整个树中。这可以减少延迟,并提高电路的性能。它通常用于分时复用(time multiplexing)和流水线(pipelining)等技术中。

怎么理解呢?可以从一个小例子来说明

假如我们要实现一个Vec集合里面的所有元素之和

那么则有以下SpinalHDL代码

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)
}

经过编译,上述代码生成了下面的verilog代码

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

我们把改代码导入到vivado软件中,查看电路概图,点击RTL ANALYSIS下的Schematic即可

在这里插入图片描述
在这里插入图片描述

可以看到,实现了四个元素的和使用了三个加法器,可以对电路进行优化,即vec0vec1相加的同时,vec2vec3也进行了相加,这样可以减少延迟,可以使用reduceBalancedTree函数

 val c = vec1.reduceBalancedTree(_ + _).asOutput

可以看到生成的verilog代码

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)
  1. vec1.reverse:这个操作对vec1进行反转。例如,如果vec1的初始值是[a, b, c, d],那么反转后的结果就是[d, c, b, a]

  2. reduceBalancedTree(_ @@ _):这个操作将反转后的vec1中的元素进行二叉树归约。使用@@运算符将两个元素连接起来,直到最终得到一个单一的元素。例如,对于[d, c, b, a],进行二叉树归约的过程如下:

    cssCopy code
    [d, c, b, a] -> [(d @@ c), (b @@ a)] -> [dcba]
    

    归约过程中,每次将两个元素连接成一个新元素,直到最终得到一个包含所有元素的向量。

  3. asBits:这个操作将归约后的结果转换为Bits类型。Bits是Chisel中表示位向量的类型。

  4. vec2.assignFromBits(...):这个操作将位向量转换后的结果赋值给vec2。这意味着vec2的每个元素将被设置为归约后的结果中对应的位。

综上所述,这段代码的作用是将vec1的元素进行反转,然后将反转后的元素通过二叉树归约连接成一个位向量,并将结果赋值给vec2的每个元素。

参考资料:1. SpinalHDL教程