1

我正在研究一种矩阵求和类型的设计。编译器需要 4+ 小时才能生成 1+ 百万行代码。每一行都是“分配.....”我不知道这是编译器效率低下还是我的编码风格不好。如果有人可以提出一些替代方案,那就太好了!

这是代码的描述输入将是一个随机矩阵元素的AND,并使用.reduce求和,所以结果矩阵应该是140X6 vec,它们一起给我一个840位的输出

(rndvec,它应该是一个 140x840x6 位的随机矩阵。因为我不知道如何生成随机值,所以我从一个固定的 140x6 开始表示一行并一遍又一遍地输入它)

以下是我的代码

import Chisel._
import scala.collection.mutable.HashMap
import util.Random

class LBio(n: Int) extends Bundle {
   var myinput = UInt(INPUT,840)
   var myoutput = UInt (OUTPUT,840)

}


class Lbi(q: Int,n:Int,m :Int ) extends Module{
   def mask(orig: Vec[UInt],maska:UInt,mi:Int)={
   val result = Vec.fill(840){UInt(width =6)}
    for (i<-0 until 840 ){
         result(i) := orig(i)&Fill(6,maska(i))  //every bits of input AND with random vector 
      }


     result
   }

  val io= new LBio(840)

   val rndvec =  Vec.fill(840){UInt("h13",6)}       //random vector, for now its just replication of 0x13....
   val resultvec = Vec.fill(140){UInt(width = 6)}

  for (i<-0 until 140){

       resultvec(i) := mask(rndvec,io.myinput,m).reduce(_+_)  //add the entire row of 6 bits element together with reduce

  }

 io.myoutput := resultvec.toBits


}

终端报告:

started inference
finished inference (4)
start width checking
finished width checking
started flattenning
finished flattening (941783)
resolving nodes to the components
finished resolving
started transforms
finished transforms
checking for combinational loops
NO COMBINATIONAL LOOP FOUND
COMPILING class TutorialExamples.Lbi 0 CHILDREN (0,0)
[success] Total time: 33453 s, completed Oct 16, 2013 10:32:10 PM
4

1 回答 1

2

您的 Chisel 代码没有明显的问题,但我应该指出,如果 rndvec 是 140x840x6 位,则状态约为 689kB!并且您的 reduce 操作处于 5kB 状态。

Chisel 使用“assign”语句,因为您的代码完全是组合的,并且 Chisel 产生了一种非常结构化的 Verilog 形式。

我怀疑杀死编译时间的部分(除了大量的状态)是您正在使用 mask() 函数生成和操作 140 个 Vecs。

我尝试重写您的代码并将其从 941,783 个节点减少到 202,723 个(编译大约需要 10-15 分钟,但会生成 11MB 的 Verilog 代码)。我很确定这与您的代码所做的一样:

class Hello(q: Int, dim_n:Int) extends Module
{
    val io = new LBio(dim_n)

    val rndvec = Vec.fill(dim_n){UInt("h13",6)}
    val resultvec = Vec.fill(dim_n/6){UInt(width=6)}

    // lift this work outside of the for loop
    val padded_input = Vec.fill(dim_n){UInt(width=6)}
    for (i <- 0 until dim_n)
    {
       padded_input(i) := Fill(6,io.myinput)
    }  

    for (i <- 0 until dim_n/6)
    {
       val result = Bits(width=dim_n*6)
       result := rndvec.toBits & padded_input.toBits

       var sum = UInt(0) //advanced Chisel - be careful with the use of var!
       for (j <- 0 until dim_n by 6)
       {
          sum = sum + result(j+6,j)
       }  
       resultvec(i) := sum
    }  

    io.myoutput := resultvec.toBits
}  

我所做的是避免一遍又一遍地做同样的工作——比如在 for 循环的 mask() 函数中填充 myinput Vec。我还将所有内容都保存在 Bits() 而不是 Vecs 中。可悲的是,这意味着我失去了很棒的 .reduce() 函数。

我认为答案可能是“意识到你正在创建多少状态”和“Vecs 很棒,但要小心使用”。

你有简短的 Verilog 版本吗?看看 Chisel 是否在某些领域失去了效率会很有趣。

于 2013-10-17T16:33:43.183 回答