logo Spade Blog

Why build a new language?

Posted 2022-09-06 by Frans Skarman

Introduction🔗

I showed off Spade at FPL 2022 this year which was a really fun experience. One of the common questions I got was "why do you build a new language", which certainly is a valid question. While I gave some sort of an answer to it in person, I wasn't super happy with it, so this post acts as an answer to that question, and gives me an opportunity to summarize my thoughts and hopefully give a more well thought out answer than I did in person at the conference.

Alternative overview🔗

If we want to start an FPGA project today, in the big picture we have three groups of options for the programming tool to use. First, and perhaps most common is using VHDL, Verilog SystemVerilog. For those of us who are a bit more adventurous and don't like the established HDLs, there are quite a few options out there in varying degrees of "finnishedness" and adoption:

  • Chisel: Domain specific language (DSL) in scala for describing hardware
  • SpinalHDL: Another Scala based DSL
  • Amaranth: Python DSL
  • Clash: Actual haskell compiled to hardware using a hint of black magic
  • Bluespec: High level HDL with a strong type system
  • TL-verilog: Verilog but with a bunch of abstractions, like pipelining
  • Pipeline-C: A very C-like HDL with auto pipelining.
  • Silice: Custom HDL language with a slightly higher abstraction than Verilog/VHDL
  • DFiant: Dataflow based HDL in scala

This list is certainly incomplete, but most of the "big" alternatives are in there, and it represents most of the "kinds" of alternative HDL that exists.

Finally, the last major option for designing hardware today is to use High Level Synthesis (HLS). Again, quite a few tools exist, however as I'll discuss in the section on HLS, I don't think any of them directly compete with a normal HDL.

Other Alt-HDLs🔗

From the discussions at FPL, I think the most interesting comparison is to other Alt-HDLs so I will start there. Given the long list of alt-HDLs it helps to divide them into categories and discuss them separately.

Embedded DSLs🔗

The first category I want to discuss and the one with the biggest adoption is those which are embedded in software languages, primarily Chisel, Spinal and DFiant which are embedded in Scala, and Amaranth which is embedded in Python.

Chisel and Spinal and Amaranth🔗

A big advantage of this model is the meta programming capabilities they provide. Being embedded in a host language, you have the whole host language available to you for all the compile time magic you want to do. You can use host language features like classes and inheritance to write object oriented hardware, and he meta programming capabilities allow you to use any control flow you like to "conditionally" instantiate. Loops, if-statements, functions returning whole modules are all easy to do.

There are, of course, some disadvantages to this approach. Being embedded in a host language means that the HDL in some ways becomes a second class citizen. For example, Scala has very powerful pattern matching features for working with sum types. However, in Chisel and Spinal, as far as I am aware, those can only match on "software values", they can not get compiled down to the underlying hardware. Similarly, the type system in scala is very powerful, but most of it can only be used for abstraction in the software side, not the hardware. Similarly, language constructs in the host language, like if statements, function calls, loops etc. are all "used up" in the host language, and therefore need alternatives when describing the corresponding operation in hardware.

At this point, it is worth mentioning that DFiant does solve the issue of pattern matching and using actual Scala constructs in hardware. However, from speaking to the author, that seems like it has been a lot of work to achieve, and as I'll discuss later, DFiant is not really a direct competitor to spade.

Another pain point of these embedded DSLs is that the error messages produced by them are often mixes of host language stack traces, types etc. and hardware problems.

NOTE: Examples needed

As a minor point which I think is still valid, though perhaps not very important: using these embedded DSLs require knowledge of both the host language and the undelying DSL. That adds friction for any potential user. While some people may not care about this, not knowing Scala, and it being quite a complex language has kept me away from Chisel and Spinal

While Spade misses out on the convenient meta programming capabilities of the DSL tools, it is a language designed from the ground up for hardware, with a powerful type system, and pattern matching on hardware values.

Clash🔗

Clash is a bit of a special case with it not being embedded in another language but rather a special Haskell compiler that can compile a significant chunk of Haskell to hardware. My only real complaint about it

Appendix: HLS🔗