前回の続き。Chisel勉強中。
このページから。
パラメータ付き関数
Polymorphism and Parameterization · freechipsproject/chisel3 Wiki · GitHub
より一般的なMuxを定義するために、ビット長をパラメータ化する。
def Mux[T <: Bits](c: Bool, con: T, alt: T): T = { ... }
この場合、TはBits
のサブクラスである必要がある。
Mux(c, UInt(10), UInt(11))
パラメータ付きクラス
Polymorphism and Parameterization · freechipsproject/chisel3 Wiki · GitHub
パラメータ付き関数のように、クラスもパラメータ化することにより、再利用しやすくすることができる。 例えば、Filterクラスを一般化する。
class FilterIO[T <: Data](gen: T) extends Bundle { val x = Input(gen) val y = Output(gen) }
Filterクラスを、Linkの型をコンストラクタとして受け取るクラスとして定義することができる。
class Filter[T <: Data](gen: T) extends Module { val io = IO(new FilterIO(gen)) ... }
一般化したFIFOは以下のように定義することができる。
class DataBundle extends Bundle { val a = UInt(32.W) val b = UInt(32.W) } class Fifo[T <: Data](gen: T, n: Int) extends Module { val io = IO(new Bundle { val enqVal = Input(Bool()) val enqRdy = Output(Bool()) val deqVal = Output(Bool()) val deqRdy = Input(Bool()) val enqDat = Input(gen) val deqDat = Output(gen) }) val enqPtr = Reg(init = 0.asUInt(sizeof(n).W)) val deqPtr = Reg(init = 0.asUInt(sizeof(n).W)) val isFull = Reg(init = false.B) val doEnq = io.enqRdy && io.enqVal val doDeq = io.deqRdy && io.deqVal val isEmpty = !isFull && (enqPtr === deqPtr) val deqPtrInc = deqPtr + 1.U val enqPtrInc = enqPtr + 1.U val isFullNext = Mux(doEnq && ~doDeq && (enqPtrInc === deqPtr), true.B, Mux(doDeq && isFull, false.B, isFull)) enqPtr := Mux(doEnq, enqPtrInc, enqPtr) deqPtr := Mux(doDeq, deqPtrInc, deqPtr) isFull := isFullNext val ram = Mem(n) when (doEnq) { ram(enqPtr) := io.enqDat } io.enqRdy := !isFull io.deqVal := !isEmpty ram(deqPtr) <> io.deqDat }
kここで、DataBundle型を受け取る8要素を格納できるFIFOを以下のようにインスタンスすることができる。
val fifo = Module(new Fifo(new DataBundle, 8))
Ready/Validのインタフェースを以下のようにして一般化することができる。
class DecoupledIO[T <: Data](data: T) extends Bundle { val ready = Input(Bool()) val valid = Output(Bool()) val bits = Output(data) }
以下のようにデータのハンドシェークを定義する。
class DecoupledDemo extends DecoupledIO(new DataBundle)
こうして、FIFOインタフェースを以下のようにして簡単かすることができる。
class Fifo[T <: Data](data: T, n: Int) extends Module { val io = IO(new Bundle { val enq = Flipped(new DecoupledIO(data)) val deq = new DecoupledIO(data) }) ... }
複数クロックドメイン
Multiple Clock Domains · freechipsproject/chisel3 Wiki · GitHub
Chisel3では、以下のように複数クロックをサポートすることができるようになった。 以下のように非同期のFIFOでデータの受け渡しを行うことができる。
class MultiClockModule extends Module { val io = IO(new Bundle { val clockB = Input(Clock()) val stuff = Input(Bool()) }) // This register is clocked against the module clock. val regClock = RegNext(stuff) withClock (io.clockB) { // In this withClock scope, all synchronous elements are clocked against io.clockB. // This register is clocked against io.clockB. val regClockB = RegNext(stuff) } // This register is also clocked against the module clock. val regClock2 = RegNext(stuff) }