プログラミング言語 Chisel

Chisel言語

Chiselの概要

Chisel(Scala埋め込み言語によるハードウェア構築)は、ハードウェア設計と検証を容易にするハードウェア構築言語です。Scalaプログラミング言語の上に構築されており、その表現力と関数型プログラミング機能を活用して、設計者が洗練されたハードウェア設計やテストベンチを簡単に作成できるようにしています。Chiselは主にデジタル回路の開発に使用され、特にFPGAやASIC設計の分野で活躍しています。

歴史的側面

創造と初期の発展

Chiselはカリフォルニア大学バークレー校で、バークレーアーキテクチャ研究グループの支援の下に研究プロジェクトとして開発されました。その創造の動機は、従来のハードウェア記述言語(HDL)であるVerilogやVHDLと比較して、より生産的で効率的なハードウェア設計手段を提供することでした。ハードウェア設計を高水準プログラミング言語に埋め込むことで、Chiselはより良い抽象化、高水準の構造、およびコードの再利用を提供することを目指しました。

進化と現在の状態

Chiselはその誕生以来、学術界や産業界で人気を博しています。この言語は、多くの開発者からの貢献により進化し、機能、ライブラリ、使いやすさが向上しました。Scalaとの統合により、設計者は関数型プログラミング、型安全性、高度なコレクションライブラリなどの強力な機能を活用できるようになりました。Chiselは現在、学術研究から商業製品に至るまで、現代のハードウェア開発プロジェクトで広く使用されています。

他の言語やプラットフォームとの関係

ChiselはVerilogやVHDLなどのHDLからインスピレーションを受けており、これらのコア概念を借用しつつ、Scalaのプログラミングパラダイムで強化しています。また、生産性と表現力に焦点を当てたSpinalHDLなどの他のハードウェア構築フレームワークとも密接に関連しています。Chiselで設計されたものはVerilogに変換できるため、既存の合成ツールやワークフローを利用することが可能です。

構文の特徴

埋め込みDSL

ChiselはScala内に埋め込まれたドメイン特化型言語(DSL)を提供し、ハードウェア設計者がハードウェア記述のためにScalaの構文を利用できるようにしています。たとえば、シンプルな2入力マルチプレクサを定義することは次のように表現できます:

class SimpleMux extends Module {
    val io = IO(new Bundle {
        val a = Input(Bool())
        val b = Input(Bool())
        val sel = Input(Bool())
        val out = Output(Bool())
    })
    
    io.out := Mux(io.sel, io.b, io.a)
}

型とビット幅

Chiselはさまざまな型をサポートし、設計者がビット幅を明示的に指定できるようにして、ハードウェアリソースの利用をより良く制御できるようにしています。たとえば:

val myWire = Wire(UInt(8.W)) // 8ビットの符号なし整数

ハードウェアコンポーネントの抽象化

この言語は一般的なハードウェアコンポーネントのための抽象化を提供します。たとえば、シンプルなレジスタを作成するには:

val reg = RegInit(0.U(8.W)) // 0で初期化された8ビットレジスタ

パラメータ化モジュール

Chiselはパラメータ化モジュールの作成を可能にし、異なる構成で再利用可能な設計を実現します:

class ParamModule(val size: Int) extends Module {
    val io = IO(new Bundle {
        val input = Input(UInt(size.W))
        val output = Output(UInt(size.W))
    })
    
    io.output := io.input + 1.U
}

条件式

Chiselは複雑なハードウェアロジックを容易にするために条件式をサポートしています:

val result = Mux(condition, trueValue, falseValue) // マルチプレクサ

ハードウェアジェネレータ

高階関数を使用してモジュラーなハードウェアコンポーネントを構築し、ハードウェア構成を生成します:

def makeAdder(n: Int) = new Module {
    val io = IO(new Bundle {
        val a = Input(UInt(n.W))
        val b = Input(UInt(n.W))
        val sum = Output(UInt(n.W))
    })
    io.sum := io.a + io.b
}

コレクションユーティリティ

ChiselはScalaのコレクションユーティリティを使用して、ハードウェア要素を効果的に操作することを可能にします:

val wires = VecInit(Seq.fill(4)(Wire(UInt(8.W)))) // 4本のワイヤのベクタを作成

順序論理

順序論理はChiselの専用構文を使用して簡単に表現できます。たとえば、レジスタを使用する場合:

when(condition) {
    reg := newValue
} .otherwise {
    reg := oldValue
}

組み込みテストフレームワーク

ChiselはScalaTestと統合されており、開発者がハードウェア設計のテストを自然に記述できるようにしています:

class MyModuleTester extends PeekPokeTester(new MyModule) {
    poke(dut.a, 1)
    poke(dut.b, 0)
    expect(dut.out, 1)
}

メソッドチェーン

Chiselはメソッドチェーンをサポートしており、複雑なハードウェア回路の定義を簡潔かつ読みやすくします:

val result = (a + b).asUInt + c

開発者のツールとランタイム

IDEとコンパイラ

ChiselはScalaをサポートする任意のIDEで開発できます。たとえば、Scalaプラグインを使用したIntelliJ IDEAなどです。また、sbt(Scala Build Tool)は、プロジェクトや依存関係を管理し、ChiselプロジェクトをVerilogコードにコンパイルするために一般的に使用されます。

プロジェクトの構築

Chiselプロジェクトを作成するには、標準的なsbtプロジェクト構造を設定できます。シンプルなbuild.sbtファイルは次のようになります:

name := "MyChiselProject"
version := "0.1"
scalaVersion := "2.12.10"

libraryDependencies += "edu.berkeley.cs" %% "chisel3" % "3.4.4"

ビルドするには、コマンドラインからsbt runを実行し、出力されたVerilogファイルはターゲットディレクトリに生成されます。

アプリケーション

Chiselは主にデジタルハードウェア設計と検証に使用されます。以下のような分野での応用があります:

他の言語との比較

Chiselは、従来のHDLであるVerilogやVHDLとは異なり、関数型プログラミング、型安全性、高水準の抽象化など、高水準プログラミング言語に見られる機能を提供します。

他の言語と比較すると:

ソースからソースへの翻訳のヒント

Chiselを他のハードウェア記述言語に翻訳するためのツールとして、ChiselコンパイラはChiselソースコードから直接Verilogを生成できます。Chiselを別のHDLに直接変換する広く知られたソースからソースへの翻訳ツールはありませんが、生成されたVerilogは必要に応じて手動で適応できます。

既存のソースからソースへのツール

現在、最も認知されているツールはChiselツールチェーン自体であり、ユーザーがChisel設計を合成可能なVerilogコードにコンパイルできるようにします。また、さまざまなライブラリやツールを通じてChiselを他のハードウェアフレームワークと統合する取り組みも行われており、異なるハードウェア設計手法間のコラボレーションと相互運用性を促進しています。