Scala 凿子编译器非常慢
我正在做一种矩阵求和的设计。编译器需要4个多小时才能生成100多万行代码。每一行都是“assign…”我不知道这是编译器效率低下还是我的编码风格不好。如果有人能提出一些替代方案,那就太好了 下面是代码的描述 输入将是和,一个随机矩阵元素接一个元素,并使用.reduce求和,因此结果矩阵应为140X6 vec,将它们组合在一起会得到840位的输出 (rndvec,应该是一个140x840x6位的随机矩阵。因为我不知道如何生成随机值,所以我从一个固定的140x6开始表示一行,并反复输入) 这是我的代码Scala 凿子编译器非常慢,scala,matrix,hdl,chisel,Scala,Matrix,Hdl,Chisel,我正在做一种矩阵求和的设计。编译器需要4个多小时才能生成100多万行代码。每一行都是“assign…”我不知道这是编译器效率低下还是我的编码风格不好。如果有人能提出一些替代方案,那就太好了 下面是代码的描述 输入将是和,一个随机矩阵元素接一个元素,并使用.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
}
您的凿子代码没有明显的错误,但我应该指出,如果rndvec是140x840x6位,则状态为~689kB!你的reduce操作是在5kB的状态下进行的 凿子使用“assign”语句,因为您的代码是完全组合的,并且凿子生成一种非常结构化的Verilog形式 我怀疑导致编译时间缩短的原因(除了大量的状态)是您正在使用mask()函数生成和操作140个向量 我试图重写您的代码,并将其从941783个节点降至202723个节点(编译大约需要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
}
类Hello(q:Int,dim\n:Int)扩展了模块
{
val io=新的LBio(尺寸)
val rndvec=Vec.fill(dim_n){UInt(“h13”,6)}
val resultvec=Vec.fill(尺寸n/6){UInt(宽度=6)}
//将此工件提升到for回路外
val padded_input=Vec.fill(dim_n){UInt(width=6)}
例如(我知道如何利用“生成”的优势吗在编写verlog代码时?如果现在我不认为有任何方法可以减少生成的verilog大小。在哪里有一个很好的示例来演示如何使用var?我将通过管道完成整个求和过程,但我不知道如何将var转换为某个reg。谢谢,我没有verilog版本。在verilog中,“generate”将使代码简短。我使用凿子这样做是因为“reduce”函数可以使求和像树一样简单。我计划用树状结构对数组求和,这将关键路径减少到O(log(n)),而不是逐个添加它们,即O(n)。你有什么建议吗?我认为“reduce”如果您能很好地完成这项任务,请查看kiffutil.scala以了解如何使用“var”的示例,特别是在构建优先级编码器时。scala变量指向凿图中的节点,因此“var”允许您更改所指向的节点。这在描述模式以及在描述模式的进一步迭代时更改所指向的节点时非常有用。缺点是,对于凿子“when()”语句,var是不可见的;相反,依赖递归赋值或Mux来获得条件赋值。
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
}