1

私は行列加算のような設計に取り組んでいます。コンパイラは、100 万行以上のコードを生成するのに 4 時間以上かかります。すべての行が "assign....." です。これはコンパイラの非効率なのか、コーディング スタイルが悪いのかわかりません。誰かが素晴らしい代替案を提案できれば!

コードの説明は次のとおりです。入力は要素ごとにランダムな行列の AND になり、.reduce を使用して合計されるため、結果の行列は 140X6 vec になるはずです。それらを一緒に猫にすると、840 ビットの出力が得られます。

(140x840x6ビットのランダム行列であると思われるrndvec。ランダムな値を生成する方法がわからないため、固定の140x6から始めて1つの行を表し、入力を何度もフィードします)

これは私のコードです

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 は非常に構造的な形式の Verilog を生成するため、Chisel は「割り当て」ステートメントを使用します。

(大量の状態は別として) コンパイル時間を短縮している部分は、mask() 関数を使用して 140 個の Vec を生成および操作していることだと思います。

私はあなたのコードを書き直して、941,783 ノードから 202,723 ノードに減らしました (コンパイルには約 10 ~ 15 分かかりますが、11 MB の 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 をパディングするなど、同じ作業を何度も行うことを避けることでした。また、すべてを Vecs ではなく Bits() に保存しました。悲しいことに、それは素晴らしい .reduce() 関数を失うことを意味します。

おそらく答えは、「作成している状態の量を認識している」と「Vec は素晴らしいですが、慎重に使用してください」だと思います。

短くて簡潔な Verilog バージョンはありますか? Chisel が効率性を失っている領域があるかどうかを確認するのは興味深いことです。

于 2013-10-17T16:33:43.183 に答える