Chisel (Constructing Hardware In a Scala Embedded Language) to język konstrukcji sprzętu, który ułatwia projektowanie i weryfikację sprzętu. Został zbudowany na bazie języka programowania Scala, wykorzystując jego ekspresyjność i możliwości programowania funkcyjnego, aby umożliwić projektantom łatwe tworzenie zaawansowanych projektów sprzętowych i testbenchy. Chisel jest głównie używany w rozwoju obwodów cyfrowych, szczególnie w dziedzinie projektowania FPGA i ASIC.
Chisel został opracowany jako projekt badawczy na Uniwersytecie Kalifornijskim w Berkeley, pod auspicjami grupy badawczej Berkeley Architecture Research. Motywacją do jego stworzenia było zapewnienie bardziej produktywnego i efektywnego sposobu projektowania sprzętu w porównaniu do tradycyjnych języków opisu sprzętu (HDL) takich jak Verilog czy VHDL. Poprzez osadzenie projektowania sprzętu w języku programowania wysokiego poziomu, Chisel miał na celu oferowanie lepszej abstrakcji, wyższych konstrukcji i ponownego użycia kodu.
Od momentu powstania, Chisel zyskał popularność w środowiskach akademickich i przemysłowych. Język ewoluował dzięki wkładom licznych programistów, co doprowadziło do ulepszeń w jego funkcjach, bibliotekach i użyteczności. Jego integracja z Scalą pozwoliła projektantom na wykorzystanie potężnych funkcji, takich jak programowanie funkcyjne, bezpieczeństwo typów i zaawansowane biblioteki kolekcji. Chisel jest obecnie szeroko stosowany w nowoczesnych projektach rozwoju sprzętu, od badań akademickich po produkty komercyjne.
Chisel czerpie inspirację z HDL, takich jak Verilog i VHDL, zapożyczając ich podstawowe koncepcje, jednocześnie wzbogacając je o paradygmaty programowania z Scali. Ma również bliski związek z innymi frameworkami konstrukcji sprzętu, takimi jak SpinalHDL, które podobnie koncentrują się na produktywności i ekspresyjności. Projekty Chisel mogą być konwertowane na Verilog, co umożliwia korzystanie z istniejących narzędzi syntezujących i przepływów pracy.
Chisel zapewnia osadzony język specyficzny dla domeny (DSL) w Scali, pozwalając projektantom sprzętu na wykorzystanie składni Scali do opisu sprzętu. Na przykład, zdefiniowanie prostego multipleksera 2-wejściowego można wyrazić w następujący sposób:
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 wspiera różnorodne typy i pozwala projektantom na wyraźne określenie szerokości bitowych, co zapewnia lepszą kontrolę nad wykorzystaniem zasobów sprzętowych. Na przykład:
val myWire = Wire(UInt(8.W)) // 8-bitowa liczba całkowita bez znaku
Język oferuje abstrakcje dla powszechnych komponentów sprzętowych. Na przykład, aby stworzyć prosty rejestr:
val reg = RegInit(0.U(8.W)) // 8-bitowy rejestr zainicjowany na 0
Chisel pozwala na tworzenie modułów parametryzowanych, co umożliwia ponowne wykorzystanie projektów z różnymi konfiguracjami:
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 wspiera wyrażenia warunkowe, aby ułatwić złożoną logikę sprzętową:
val result = Mux(condition, trueValue, falseValue) // Multiplekser
Twórz modułowe komponenty sprzętowe za pomocą funkcji wyższego rzędu do generowania konfiguracji sprzętowych:
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 pozwala na korzystanie z narzędzi kolekcji Scali do efektywnego manipulowania elementami sprzętowymi:
val wires = VecInit(Seq.fill(4)(Wire(UInt(8.W)))) // Tworzenie wektora 4 przewodów
Logika sekwencyjna jest łatwo wyrażana za pomocą dedykowanych konstrukcji Chisel, takich jak rejestry:
when(condition) {
reg := newValue
} .otherwise {
reg := oldValue
}
Chisel integruje się z ScalaTest, co umożliwia programistom naturalne pisanie testów dla ich projektów sprzętowych:
class MyModuleTester extends PeekPokeTester(new MyModule) {
poke(dut.a, 1)
poke(dut.b, 0)
expect(dut.out, 1)
}
Chisel wspiera łańcuchowanie metod, co pozwala na zwięzłe i czytelne definiowanie złożonych obwodów sprzętowych:
val result = (a + b).asUInt + c
Chisel można rozwijać przy użyciu dowolnego IDE, które wspiera Scalę, takiego jak IntelliJ IDEA z wtyczką Scala. Dodatkowo, sbt (Scala Build Tool) jest powszechnie używany do zarządzania projektami i zależnościami, a także do kompilacji projektów Chisel do kodu Verilog.
Aby stworzyć projekt Chisel, można ustawić standardową strukturę projektu sbt. Prosty plik build.sbt
może wyglądać tak:
name := "MyChiselProject"
version := "0.1"
scalaVersion := "2.12.10"
libraryDependencies += "edu.berkeley.cs" %% "chisel3" % "3.4.4"
Aby zbudować, należy uruchomić sbt run
z linii poleceń, a wygenerowane pliki Verilog będą znajdować się w katalogu docelowym.
Chisel jest głównie używany w projektowaniu i weryfikacji sprzętu cyfrowego. Znajduje zastosowanie w takich obszarach jak:
Chisel wyróżnia się na tle tradycyjnych HDL, takich jak Verilog i VHDL, oferując funkcje spotykane w językach programowania wysokiego poziomu, takie jak programowanie funkcyjne, bezpieczeństwo typów i wyższe abstrakcje.
W porównaniu do innych języków:
Aby przetłumaczyć Chisel na inne języki opisu sprzętu, narzędzia takie jak kompilator Chisel mogą generować Verilog bezpośrednio z kodu źródłowego Chisel. Nie ma powszechnie znanych narzędzi do tłumaczenia źródło-do-źródła, które konwertują Chisel bezpośrednio na inny HDL, ale wygenerowany Verilog można ręcznie dostosować, jeśli zajdzie taka potrzeba.
Obecnie najbardziej rozpoznawanym narzędziem jest sam zestaw narzędzi Chisel, który pozwala użytkownikom kompilować projekty Chisel do syntetyzowalnego kodu Verilog. Istnieją również wysiłki na rzecz integracji Chisel z innymi frameworkami sprzętowymi poprzez różne biblioteki i narzędzia, co sprzyja współpracy i interoperacyjności między różnymi metodologiami projektowania sprzętu.