Current Interests / Top Of Mind

Posted on May 12, 2023

Extremely Eager, Eager, and Lazy Programming Languages

Most hardware description languages, in a sense, are extremely eager. The logic described always runs. In contrast, most programming languages are lazy, as functions described only run when called. Haskell is extremely lazy in this regard.

Bluespec is somewhere between lazy and extremely eager. Functions/rules always run, but only when they legally can. Functions/rules in Bluespec will only run if they can do so atomically, which is a necessary condition for concurrency safety in the broader context of programming languages that aren't purely functional.

The need for exposing atomic-related semantics at the source code level entirely disappears when you restrict your language paradigm to be purely functional with laziness, which is precisely what Clash-Haskell offers. In Bluespec, the designer is allowed and even encouraged to describe multiple entities that can contend for the same resource, leaving the compiler to resolve such contentions before emitting a circuit. In purely functional Clash, however, this is not possible, which might seem to reduce the designer's expressive power. Clash compensates by exposing the powerful abstractions native to Haskell to the designer.

Merging Hardware and Software

What Hasn't Been Working

There have been many attempts to compile C to hardware, but this field has never really taken off because:

  1. C is too permissive with its type system.
  2. Fast hardware implementations require a good hardware architecture, and to date, there hasn't been much research effort towards making manual architectural exploration easier or improving compiler-automated architectural exploration.

What Could Work

Clash-Haskell easily allows for developing models of mixed resolution, making it possible to rapidly explore architectural tradeoffs of an algorithm's implementation before iteratively refining that algorithm into incrementally better circuits.

It turns out that a purely functional language with lazy semantics, such as Haskell, maps extremely well to digital-logic circuits. Clash Haskell allows you to iteratively refine a large subset of possible Haskell programs into valid circuits.

Correctness By Construction

Circuit design in Clash seems to come very close to correct-by-construction design (at least when designing in a purely functional style). For example, consider the following Verilog code:

    always @ (en or d)
        if (en)
            q = d;

Notice that the previous Verilog block is missing an else block, but it is still valid Verilog.

Purely functional Clash (which is just purely functional Haskell) doesn't allow for this and is much more akin to describing a netlist, but with provisions for incredibly high levels of abstraction.

d = q if en else 0

I'd say Clash is currently the state of the art when it comes to merging hardware and software.

Differentiable Programming

In theory, it is possible to compute the gradient of a program's output with respect to the program's inputs in purely functional languages such as Haskell, making certain classes of programs inherently optimizable in nature.

PyTorch and TensorFlow are obviously differentiable programming frameworks, but they are not really considered general-purpose. There is currently some interest in investigating how to construct a general-purpose differentiable programming language.

I'd like to see how this area evolves, and in particular, I'd like to understand the mechanisms needed to differentiate a function that has recursion.