Chiselを勉強するためにはとりあえず自分専用の拡張Chiselを作ってみるのが良いと思う。 とりあえずは、まずは手っ取り早く新しいデータ型でも追加してみたい。Chiselには以下の基本データ型が存在する。
UInt
SInt
Bool
そこで、これに追加して今度はTInt
という型を追加してみる。TInt
は特に何もできない新しいデータ型で、役割はUInt
と大して変わらない。
そして、TInt
に追加する新たな演算子として、代入演算子::=
というものを追加してみる。
この演算子も限りなく意味のないものだが、A ::= B
でB
をビット反転してA
に格納する。
TInt
型を追加する
まず、UInt
, SInt
などが定義されているのは./chiselFrontend/src/main/scala/chisel3/Data.scala
で定義されている。
これに新たにTInt
クラスとTIntFactory
を追加する。
TInt
クラスはUInt
クラスをベースにして派生する。
/** A data type for unsigned integers, represented as a binary bitvector. Defines arithmetic operations between other * integer types. * * @define coll [[UInt]] * @define numType $coll * @define expandingWidth @note The width of the returned $coll is `width of this` + `1`. * @define constantWidth @note The width of the returned $coll is unchanged, i.e., `width of this`. */ sealed class TInt private[chisel3] (width: Width) extends UInt(width) with Num[UInt] { /** Connect this $coll to that $coll mono-directionally and element-wise. * * This uses the [[MonoConnect]] algorithm. * * @param that the $coll to connect to * @group Connect */ def ::= (that: TInt)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Unit = { this.connect(~that)(sourceInfo, connectionCompileOptions) // scalastyle:ignore line.size.limit } } // This is currently a factory because both Bits and TInt inherit it. trait TIntFactory { /** Create a UInt type with inferred width. */ def apply(): UInt = apply(Width()) /** Create a UInt port with specified width. */ def apply(width: Width): UInt = new UInt(width) /** Create a UInt literal with specified width. */ protected[chisel3] def Lit(value: BigInt, width: Width): UInt = { val lit = ULit(value, width) val result = new UInt(lit.width) // Bind result to being an Literal lit.bindLitArg(result) } /** Create a UInt with the specified range */ def apply(range: Range): UInt = { apply(range.getWidth) } /** Create a UInt with the specified range */ def apply(range: (NumericBound[Int], NumericBound[Int])): UInt = { apply(KnownUIntRange(range._1, range._2)) } }
このTInt
型にはTIntFactory
が追加されている。これはUIntFactory
と同一である。
TInt
型に::=
演算子を追加する。
そして、TInt
型には::=
型を追加した。これは:=
の実装をコピーしているのだが、一点だけ、connect
をする前にビット反転の演算子を挿入している。
def ::= (that: TInt)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Unit = { this.connect(~that)(sourceInfo, connectionCompileOptions) // scalastyle:ignore line.size.limit }
ついでに、派生元のUInt
にも::=
演算子がないとコンパイル中に怒られたので追加する。
diff --git a/chiselFrontend/src/main/scala/chisel3/Bits.scala b/chiselFrontend/src/main/scala/chisel3/Bits.scala index 5a6db7c1..571a3100 100644 --- a/chiselFrontend/src/main/scala/chisel3/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/Bits.scala @@ -902,6 +902,10 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U private def subtractAsSInt(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = binop(sourceInfo, SInt((this.width max that.width) + 1), SubOp, that) + + def ::= (that: Bits)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Unit = { + this.connect(~that)(sourceInfo, connectionCompileOptions) // scalastyle:ignore line.size.limit + } } // This is currently a factory because both Bits and UInt inherit it.
この::=
演算子は、実行される場合に呼ばれるのはMonoConnect
クラスのメソッドだ。MonoConnect
クラスにTInt
同士の接続を行うパタンを追加する。
diff --git a/chiselFrontend/src/main/scala/chisel3/internal/MonoConnect.scala b/chiselFrontend/src/main/scala/chisel3/internal/MonoConnect.scala index ace7be20..833106e7 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/MonoConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/MonoConnect.scala @@ -81,6 +81,8 @@ private[chisel3] object MonoConnect { elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod) case (sink_e: UInt, source_e: UInt) => elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod) + case (sink_e: TInt, source_e: TInt) => + elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod) case (sink_e: SInt, source_e: SInt) => elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod) case (sink_e: FixedPoint, source_e: FixedPoint) =>
- テストをする
まず、上記の改造を行ったChiselをコンパイルし、ローカル環境にデプロイする。
sbt publishLocal
終了すると、以下のテストコードを作成した。
test_tint.scala
package tint_test import chisel3._ class tint_test extends Module { val io = IO(new Bundle { val in = Input(TInt(8.W)) val out = Output(TInt(8.W)) }) io.out ::= io.in } object main extends App { chisel3.Driver.emitVerilog(new tint_test()) }
TInt
型と、::=
演算子を使用して配線の接続を行っている。ではさっそくコンパイルしてみよう。
sbt 'runMain tint_test.main`
コンパイルの結果、以下のVerilogファイルが生成された。
module tint_test( input clock, input reset, input [7:0] io_in, output [7:0] io_out ); assign io_out = ~ io_in; // @[tint_test.scala 11:10] endmodule
正しく生成されているようだ。