可以凿子将firrtl转换为并行/多CPU的verilog吗?

时间:2017-06-30 14:47:59

标签: parallel-processing chisel

我在凿子中设计了一个网格阵列的寄存器,比如32x32字节的D-flipflop,试图在凿子中实现这种平行的硬件拱。 firrtl文件就像100k行,看起来像网表。然后,从firrtl到verilog的翻译所耗费的时间就好几个小时。在这段时间内,处理只安排在一个CPU上。 你能否告诉我如何让它在CPU上并行运行?

关键代码:

val reg_vec = (0 to 31).map(i=>
                (0 to 31).map(j=>
                  Module(new MyNodeOfReg(8))
  )
)

scala编译器和代码运行器版本2.11.8

我做了这样的批处理,做./run然后等待./target/Bench.v:

mkdir target
cp /opt/eda_tool/RISCV/top.cpp target
scalac -d target -cp $CP Top.scala Test.scala
scala  -cp $CP org.scalatest.run Test

在scala安装后自动生成scalac / scala 其中My Test.scala是:

import chisel3._
import chisel3.util._
import chisel3.testers._
import org.scalatest._
import org.scalacheck._
import org.scalatest.prop._
import scala.sys.process._

class Bench() extends BasicTester {
  val dut = Module(new Top())
  val t = Reg(UInt(width=32),init=0.U)
  t := t+1.U

  when(t<=1.U) {
  }.elsewhen(t===100.U) {
    stop()
  }
}

class Test extends PropSpec with PropertyChecks {

  property("elaborate") {
    Driver.elaborate (() => { new Top() })
  }

  property("should return the correct result") {
    TesterDriver.execute(() => { new Bench() })
  }

}

Top.scala是:

import chisel3._
import chisel3.util._

object ce_pm{
  val div = 4
  val e = 1   
  val ec= 1   
  val p = 10 // 16/div        
  val s = p*p       
  val w = s*e       

  val ext = 64      
  val extw= ext*e   

  val irp = 20 // 40/div  // InREG parameter
  val irn = irp*irp // InREG reg number
}

class Mux4(n: Int) extends Module {
  val io = IO(new Bundle{
    val i = Input(Vec(4,UInt(n.W)))
    val s = Input(UInt(2.W))
    val o = Output(UInt(n.W))
  })
  val mux00 = Wire(UInt(n.W))
  val mux01 = Wire(UInt(n.W))
  mux00 := Mux(io.s(0)===1.U,io.i(1),io.i(0))
  mux01 := Mux(io.s(0)===1.U,io.i(3),io.i(2))
  io.o  := Mux(io.s(1)===1.U,mux01,mux00)
}

class CEIO_TwoD_Torus extends Bundle {
  val n = Input(UInt(ce_pm.e.W))
  val s = Input(UInt(ce_pm.e.W))
  val w = Input(UInt(ce_pm.e.W))
  val e = Input(UInt(ce_pm.e.W))
}

class TwoD_TorusReg extends Module {
  val io = IO(new Bundle{
    val i = new CEIO_TwoD_Torus()
    val o = new CEIO_TwoD_Torus().flip
    val d = Input(UInt(ce_pm.e.W)) 
    val c = Input(Vec(4,UInt(1.W)))
  })
  val r = Reg(UInt(ce_pm.e.W),init=0.U)
  val u_mux4 = Module(new Mux4(ce_pm.e))
  u_mux4.io.i(0) := io.i.e
  u_mux4.io.i(1) := io.i.s
  u_mux4.io.i(2) := io.i.w
  u_mux4.io.i(3) := io.i.n
  u_mux4.io.s    := Cat(io.c(2),io.c(1))
  when (io.c(0) === 1.U) {
    when (io.c(3) === 0.U) {
      r := u_mux4.io.o
    } .otherwise {
      r := io.d
    }
  } 
  io.o.e := r
  io.o.s := r
  io.o.w := r
  io.o.n := r
}

class Top extends Module {
  val io = IO(new Bundle{
    val i = Input (UInt(ce_pm.extw.W))
    val o = Output(Vec(ce_pm.p,Vec(ce_pm.p,UInt(ce_pm.e.W))))
    val c = Input (UInt(7.W))
  })
  val n  = ce_pm.irp
  val r_vec = (0 to n-1).map ( i=>
                (0 to n-1).map ( j=>
                  Module(new TwoD_TorusReg)
                )
              )
  for (i <- 0 to n-1) {
    for (j <- 0 to n-1) {
      r_vec(i)(j).io.c(0) := io.c(1)
      r_vec(i)(j).io.c(3) := io.c(0)
      r_vec(i)(j).io.c(2) := io.c(2)
      r_vec(i)(j).io.c(1) := io.c(3)
    }
  }
  // out
  val m = ce_pm.p
  for (i <- 0 to m-1) {
    for (j <- 0 to m-1) {
      io.o(i)(j) := r_vec(i)(j).io.o.e
    }
  }
  //2-D-Torus interconnection
  for (i <- 1 to n-1) {
    for (j <- 1 to n-1) {
      r_vec(i)(j).io.i.w := r_vec(i)(j-1).io.o.e
      r_vec(i)(j).io.i.n := r_vec(i-1)(j).io.o.s
    }
  }
  for (i <- 0 to n-2) {
    for (j <- 0 to n-2) {
      r_vec(i)(j).io.i.e := r_vec(i)(j+1).io.o.w
      r_vec(i)(j).io.i.s := r_vec(i+1)(j).io.o.n
    }
  }
  for (i <- 0 to n-1) {
    r_vec(i)(0).io.i.w := r_vec(i)(n-1).io.o.e
    r_vec(0)(i).io.i.n := r_vec(n-1)(i).io.o.s
  }
}

2 个答案:

答案 0 :(得分:1)

这听起来像是一个非常粗糙的性能错误,所以如果你能提供有关你的设计的更多信息会非常有用(或者代码会更好)。您还可以尝试使用命令行选项-ll info来提供每个Firrtl传递的运行时。

基于rocket-chip的项目经常会生成数十万到数百万行,这些行通常按秒到几分钟的顺序编译。出于这个原因,我们还没有觉得需要并行化代码。

编辑: 感谢您添加代码!

我努力重现您所看到的性能问题。使用irp = 32,从Firrtl到Verilog的编译大约需要4秒钟;包括Chisel在内的总编辑大约需要8秒钟。我是否应该更改其他参数?我正在编译:

object Main extends App {
  chisel3.Driver.execute(args, () => new Top)
} 

您能否分享一下您如何构建模块的更多信息?

答案 1 :(得分:0)

@jkoenig根据你的建议,我找到了新的东西。

首先,因为我有Bench.fir,所以我直接运行firrtl

  

firrtl -i Bench.fir -o my.v -X verilog

然后在几秒钟内生成verilog,就像你说的那样快。哇〜

其次,我在Top.scala中添加了这段代码

package mytest
object GenVlgTop extends App {
  chisel3.Driver.execute(args, () => new Top)
}

更新运行

scalac -d target -cp $CP Top.scala 
scala  -cp $CP mytest.GenVlgTop

然后./run生成firrtl的时间非常长,就像之前一样

[info] [0.002] Elaborating design...
[info] [1.290] Done elaborating.

日志停止并在此处等待,而未生成firrtl。

到目前为止,解决方案是这样的:

1. do the original ./run, when it's waiting, 
2. C-c to interrupt the processing
3. firrtl the generated *.fir