ハードウェアの気になるあれこれ

技術的に興味のあることを調べて書いてくブログ。主にハードウェアがネタ。

Chisel3.4.0のリリースノートを確認した(5) - groupオブジェクト

スポンサーリンク

Chisel3.4.0の変更点確認の5回目&最後(のはず)の記事。今回は#1073で追加されたgroupオブジェクトについて。

(#1073) Grouping Chisel API, added a chisel annotation API for triggering the firrtl.transforms.GroupComponents transformation.

前回のverificationオブジェクトと同じくexperimental扱いではあるが、PR #1073でgroupというオブジェクトが追加されている。

groupオブジェクトの説明には、次の様な記載がある。

scala /** Marks a set of components (and their interconnected components) to be included in a new * instance hierarchy.

この内容からするに、groupに指定したChiselのハードウェアをモジュールとしてまとめてくれるような機能っぽい。

groupオブジェクト

追加されたオブジェクトに準備されているapplyメソッドは次のようなもの。

   /*
    * @param components components in this group
    * @param newModule suggested name of the new module
    * @param newInstance suggested name of the instance of the new module
    * @param outputSuffix suggested suffix of any output ports of the new module
    * @param inputSuffix suggested suffix of any input ports of the new module
    * @param compileOptions necessary for backwards compatibility
    * @tparam T Parent type of input components
    */
  def apply[T <: Data](
      components: Seq[T],
      newModule: String,
      newInstance: String,
      outputSuffix: Option[String] = None,
      inputSuffix: Option[String] = None
  )(implicit compileOptions: CompileOptions): Unit = {

とりあえず、第一引数のcomponentsにまとめたい信号をSeqで渡せば良さそうな雰囲気で、後の引数はインスタンスされるモジュールの命名に影響するものの様子。

ということで、サンプルコードを、と思ったのだが@exampleとしてコードが準備されていたので、まずはそれをそのまま使用して確認してみよう。

import chisel3._
import chisel3.util._
import chisel3.util.experimental.group

// モジュール名は変えたけど、次のコードを拝借したもの
// src/main/scala/chisel3/util/experimental/group.scala:L.13
// https://github.com/chipsalliance/chisel3/blob/23f9f71e51c8187d732fbce6a53ef2cbfc60d4f6/src/main/scala/chisel3/util/experimental/group.scala#L13
class TryGroup extends Module {
  val io = IO(new Bundle {
    val a = Input(Bool())
    val b = Output(Bool())
  })
  val reg1 = RegInit(0.U)
  reg1 := io.a
  val reg2 = RegNext(reg1)
  io.b := reg2
  group(Seq(reg1, reg2), "DosRegisters", "doubleReg")
}

object ElaborateTryGroup extends App {
  println((new stage.ChiselStage).emitVerilog(new TryGroup))
}

これをエラボレートして生成したRTLは次のようになった。 確かにgroupで指定したレジスタが別のモジュールとして、切り出され、そのモジュールがインスタンスされている。 Chiselのモジュールにするほどではないけど、モジュール内の論理を構造化したいときとかに使えそうかな?という感じ。 inputSuffix/outputSuffixも指定できるので、グループ化の際に指定しておくと生成後のRTLの可読性を上げられそう。

module TryGroup(
  input   clock,
  input   reset,
  input   io_a,
  output  io_b
);
  wire  doubleReg_clock;
  wire  doubleReg_reset;
  wire  doubleReg_reg2_0;
  wire  doubleReg_io_a;
  DosRegisters doubleReg (
    .clock(doubleReg_clock),
    .reset(doubleReg_reset),
    .reg2_0(doubleReg_reg2_0),
    .io_a(doubleReg_io_a)
  );
  assign doubleReg_clock = clock;
  assign doubleReg_reset = reset;
  assign io_b = doubleReg_reg2_0; // @[TryGroup.scala 14:8]
  assign doubleReg_io_a = io_a;
endmodule
module DosRegisters(
  input   clock,
  input   reset,
  output  reg2_0,
  input   io_a
);
  reg  reg1; // @[TryGroup.scala 11:21]
  reg  reg2; // @[TryGroup.scala 13:21]
  assign reg2_0 = reg2;
  always @(posedge clock) begin
    if (reset) begin // @[TryGroup.scala 11:21]
      reg1 <= 1'h0; // @[TryGroup.scala 11:21]
    end else begin
      reg1 <= io_a; // @[TryGroup.scala 12:8]
    end
    reg2 <= reg1; // @[TryGroup.scala 13:21]
  end
endmodule

ということで短いけどgroupの紹介でした。