We’d love your feedback on using Clash

The Clash compiler team is actively looking to better understand how Clash is used in practice and where it can be improved. We’re especially interested in hearing from the community about anything that gets in the way of using Clash effectively.

This includes (but isn’t limited to):

  • Pain points or friction you encounter in day-to-day usea

  • Features or workflows that feel unintuitive, limiting, or incomplete

  • Issues that have slowed you down or stopped you from using Clash altogether

  • Improvements that would make Clash more useful or enjoyable for your use cases

Both high-level feedback and very specific examples are valuable to us. Whether you’re a long-time user or someone who tried Clash and moved on, we’d really appreciate hearing your perspective. Your input helps us prioritize improvements and shape the future direction of Clash.

Thanks for taking the time to share your experience, we’re listening. You can reply in this thread with your experiences or message me privately.

Hi Rowan - here’s a hastily put-together list. Some of these I’ve mentioned before, and some of them (for all I know) may be problems inherent to the domain - I’m just putting them here anyway, ignore the ones which don’t make sense. We’re generally happy with Clash, and of all the bits of our stack, it’s one of the easiest to work with.

  • circuit-notation has incomprehensible error messages and currently no documentation (other than that it’s useful and increases code clarity).
  • stalling circuits are very hard to debug - nowadays these are usually related to/solved by the lazy evaluation of tuples, but the underlying cause of this problem, and therefore when it appears, I’not sure I fully understand.
  • might be nice to use GADTs for some state machines, if I recall correctly the clash compiler can’t handle these
  • a few times we’ve had the issue that a variable in the generated verilog has been given a name which is a reserved keyword in verilog, this may have been solved by now though
  • about every two or three months I’ll see a compiler error, these are disconcerting but have always gone away with a bit of re-jigging of the code
  • we’re currently writing both property tests (using the clash-protocols hedgehog harness; for circuits where there isn’t really any path dependency) and unit tests (using signalAutomaton; for ciruits where there is path dependency, ie it does matter which order the inputs are given in). It would be really nice to have a type of test which has both these features - randomly generated inputs, but can handle path dependency. Elliot has briefly tried to write one but hasn’t yet succeeded because of constraints with signalAutomaton.
  • we’ve briefly tried DSignal, but didn’t find it really fitted our use case, and it felt like it wasn’t yet fully implemented (or maybe, was an impossible-to-fully-implement concept). It doesn’t have its own versions of eg mealy or other common functions, so I found I was having to use the normal mealy, then manually add the delay type notations, and that defeated the point a bit.
  • This is probably more of a convention than a structural change, but it would be nice if the clash-provided libraries had some universal way of distinguishing between bits and bytes when dealing with wire sizes. In most of the code, Wire n means a wire of n bits’ width, but in places it means n bytes’ width.

Hi Chris,

Thanks for your points. Most of them are clear to me but some I’m not sure what you mean. So I’d appreciate if you could clarify:

about every two or three months I’ll see a compiler error, these are disconcerting but have always gone away with a bit of re-jigging of the code

Clear, we would always appreciate bug reports for these. If you don’t want to spend the time to make a small reproducer and can’t release the code openly you can also message me larger chunks of code so I can minimize it. In the end compiler errors should not happen so we are keen to resolve these!

This is probably more of a convention than a structural change, but it would be nice if the clash-provided libraries had some universal way of distinguishing between bits and bytes when dealing with wire sizes. In most of the code, Wire n means a wire of n bits’ width, but in places it means n bytes’ width.

Do you mean on the clash source code side of things? There we have `BitSize Foo` to get the number of bits to represent Foo. You can DivRU (BitSize Foo) 8to get the number of bytes. On the generated HDL side of things I’m not sure what you could be referring to.

Hi Rowan,

Yes, I always feel a bit guilty when I hit a compiler bug and don’t report it, I’ll try to be a better citizen in future.

For the data widths, I was thinking of this:

  • BitSize (Unsigned 8) is 8 bits.

- DataWidth (Axi4StreamConfig 8 1 1) is 8 bytes.
Which is not obvious from the code alone.