Hacker News new | ask | show | jobs
by Traster 2393 days ago
FPGAs are fundamentally a dataflow system. You have geographically distributed compute units, with reconfigurable routing. CPUs (obviously) work by bringing the data to a single fixed central processing unit. So the key question for all these software->FPGA tools, is how they handle this transformation. The problem is that often the way you layout your program is introducing implicit constraints that prevent optimization that aren't real but simply an artefact of how you write software.

The thing is, I don't believe that transformation is a solvable problem (not least because really clever people keep trying and keep releasing terrible attempts). In real life, people program GPUs using special constructs and instructions. Hell, they use special instructions for the vector operations on CPUs. So why are we pretending you can write generic code in languages designed for CPUs and have them run performantly on FPGA? What you end up with a tiny subset of the language that maps to already existing hardware languages with a little bit of syntactic sugar and a boat load of misunderstanding of the limitations.

3 comments

As to the optimization and the user not being able to and/or not having the tools to do it.

This was one of my favorite uses for ML. However the specific result i remember wasn’t that useable. The short version was they asked a model to program this FPGA to make a 1khz sin wave on a pin hooked to a speaker by listening to the result. It eventually worked, and the FPGA did indeed output a 1KHz wave. But... when the logic gates set in the FPGA were examined it was nonsense. And it wouldn’t work on any other chip. It was using defects in the silicon and was truly a one off success.

Obviously this optimization is only possible for a machine but yes, the tools from high level to bitstream could be a ton better.

The transformation is surely a solvable problem given that various HLS tools, OpenCL for FPGAs and Hastlayer exist :). Whether it makes sense is another question and I don't pretend to have the definitive answer, though I believe it does: abstractions can increase productivity with trade-offs like the runtime efficiency of the implementation.

In this case I think in certain use-cases it has value to use the standard .NET parallel programming model and development workflow to get not an optimal but a good enough hardware implementation. The point is to get a performance and power efficiency increase, and with Hastlayer this is possible for certain algorithms with the fraction of the knowledge and time (i.e. cost) required to even begin being productive with HDL languages. Whether this is the best approach for a given task depends on its context.

We'll see, and in the meantime we keep working on experimental approaches like Hastlayer. Feedback like yours really helps, so thank you!

> So why are we pretending you can write generic code in languages designed for CPUs and have them run performantly on FPGA?

Because software people have never paid a cost for state in their programming.

Software folks are so poor at managing state that some clever people actually built entire languages around that fact (garbage collection).

I'm optimistic though--Rust is really the first example of "Managing state is pain in the ass--maybe we need to rethink this" that exists in programming languages. I suspect more are to follow.

Rust is really the first example of "Managing state is pain in the ass--maybe we need to rethink this" There was Ada decades ago. I could also say react... The word that you use: state is too vague to my taste.
> There was Ada decades ago.

Which then morphed into VHDL on hardware. So, fair point.

I really don't understand why Ada never caught on and I don't understand why it isn't getting a renaissance.

> The word that you use: state is too vague to my taste.

I chose "state" explicitly because it encompasses volatile memory, data persistence (file systems and the like), connections between things, etc.

All of these things have a significant cost when you are designing hardware, memory is often flip flops and highly constrained, data persistence requires a LOT of abstraction to use, connections between things cost time, possibly pins (a limited resource) and possibly an interface specification.

Hardware designers suffer real, genuine pain when a new feature needs to appear--can that fit on the chip, will that affect maximum frequency, did the cost just go up, and only then how long will that take to design and debug.

Ada never caught on for several reasons:

The compilers were priced in values totally out of reach for most mortals, which ended up buying Modula-2 or Pascal compilers instead.

On UNIX systems, it meant buying an additional compiler beyond the C one that was already on the box. When UNIX SDKs became commercial, you had to buy two (UNIX SDK + Ada), which was even less appealing.

C++ was still coming into the world, and most compiler vendors though that Ada was impossible to be fully implementable and thus never bothered. Ironically, Ada compilers are much simpler than C++ ones.

Finally nowadays from around 6 surviving compiler vendors, only GNAT is community friendly (in spite of the usual license discussions), the remaining ones keep selling their compilers at enterprise prices (talk first with the sales team way).

So it is hard to get mass adoption this way.

Ada would do better if they adopted a cleaner and more c-like syntax. It's just ugly, and people don't want to write it. But it is awesome!
Ehm, functional languages do too by avoiding state as much as possible. See https://clash-lang.org
Functional languages somewhat avoid shared or implicit state by making you pass everything in and then create something new on the way out.

That's a LOT of state even if it isn't shared. At some point, what went in and what went out needed to get stored by somebody.

Thus leading to the old Perlis adage "LISP programmers know the value of everything and the cost of nothing."

> Functional languages somewhat avoid shared or implicit state by making you pass everything in and then create something new on the way out.

Dataflow, in other words. You pass data through functions, and you know the whole thing works because the functions are composable because they aren't doing anything off to the side. No side-effects means you can think in a pipeline data flows through.

Spreadsheets achieve this quite nicely, and are the only successful visual programming language (pacem Microsoft's use of "Visual" as a marketing term for their decidedly text-based Visual Basic and Visual C++) in addition to being the forgotten programming paradigm, or at least the one most likely to be pointedly ignored.

Some of this might even have relevance for creating FPGAs based on dataflow models.