It’s almost over. I have to get my thesis signed, take a final, and give a demo and then that’ll be it. Degree #2 will be in my hands and I can begin the process of… well I’ll tell that story later.
I’ve been able to get practically nothing done on personal projects this year. I did manage to do some work with ACRIS and lpctrl to build an interface that would let me control my lighting system with my Novation Launchpad. I used this for a performance for MIT’s annual Steer Roast. I’ll do a demo video for this at some point soon. It was pretty cool, although I ran into some latency and crashing issues.
But I don’t want to talk about that either. I want to talk about the beat tracker I built and what it taught me about Bluespec. As I had posted before, I got it working a while ago and have been tweaking it a bit since then to make it work better. It figures out the tempo of most tracks pretty well, but there are some serious problems with the design and they all stem from the beat classifier module, i.e. the module that reports when it thought it detected a beat. First, it’s not very accurate — it should be using the variance of energies to determine how much higher the most recent energy has to be compared to the average energy. Secondly, it doesn’t report on how confident it thought it saw a beat. This is important because it should dictate how much the metronomes adjust their own phase.
I’m going to post a demo video up soon.
I made this project for Arvind’s Bluespec class, 6.375. Arvind was the professor whose grad student originally came up with the idea for Bluespec. The class had a bunch of labs where you’d learn different advantages of Bluespec over traditional hardware design. Theoretically, you’d do these labs, discover how magical this new programming paradigm is, and use it forever after for all your hardware design needs.
Now, don’t get me wrong. There’s some stuff that Bluespec does right. Or at least, there’s some stuff that the Bluespec developers have thought about that I think was good for them to think about. For example, Bluespec makes it easy to build complex state machines and circular pipelines using properly crafted rules. It features some nice libraries for manipulating numbers. But it doesn’t take these far enough. I had some thoughts with regard to developing a new language that would make it easy for developers to create their own number systems by specifying different attributes or capabilities (saturating vs. non-saturating arithmetic, unsigned vs. two’s complement vs. one’s complement vs. Gray coding number representation, etc.) One of these days, I’ll try to expand on that underlying idea to see if it’s actually useful… I think it will be.
Bluespec is great for prototyping and simulating your ideas — it allows you to produce a lot of hardware very fast and play around with subtle configuration changes. It makes producing a gold-standard, bit-accurate model really easy. This does not, however, mean that Bluespec is good for producing an actually implementable design. Something occurred to me while I was watching the other students in the group present on their project results: Bluespec adds a lot of overhead because it deceives people into thinking how much or little hardware a given portion of their design might produce.
For example, it’s pretty easy to make a FIFO in Bluespec. Do you want a FIFO? Easy, just
mkFIFO(). But what does that actually produce? Well, it draws upon a 150-line verilog file corresponding to a FIFO of depth 1 (larger FIFOs are chained together, I think). And this file actually produces an enormous amount of hardware. But, it does make producing a nice pipeline much easier.
Most students in the class took an existing algorithm that solved some problem (like image compression, flow analysis, etc.), re-implemented it in Bluespec, and tested it on an FPGA to see if their results were actually accelerated. The interface that most students to push data onto and pull data off of the FPGA used was called SCE-MI; we had used this framework a few times during the class. But, it’s not really suitable for a lot of applications due to bandwidth and latency limitations.
It’s just… ugh, SO MUCH STUFF when the designs don’t have to be so large.
And it showed in the students’ results. Most students found while they achieved correctness, they got little to no actual speed-up. I also realized that most students in the class were algorithms/comp sci people and I was more or less the only hardware person in the group. It seemed like a lot of those people drew incorrect conclusions about hardware design being inefficient and not worth it. I just wanted to keep yelling “no, it’s Bluespec, I swear!”
I was the only one who had a live demo at the presentations. I was even lucky in a sense; I ran out of time to do a lot of the more complicated things that I wanted to do because it just took me forever to figure out how the hell Bluespec does things. For example, it turns out that their
FixedPoint library makes some strange choices in its arithmetic library that make it impossible to do what I want it to do. Since my project also sat on a measly Spartan 3A FPGA, it was also hard to meet timing and resource constraints. In my talk, I kind of ripped on a few parts about BlueSpec that I really didn’t like and then later realized that Arvind had invited Bluespec engineers to the presentations. Oops.
They were actually surprised that I managed to get Bluespec to compile to a verilog module and include it in a VHDL project. Apparently that’s very rare. But to me, that’s probably the best way to use it: design optimized hardware with VHDL or verilog and then include the parts of your design that are complicated but not yet optimized (i.e. the Bluespec components). Then, as you optimize each of those modules, you can replace the Bluespec modules with low-level ones.
I think the summary here is this. At the beginning of the class, Arvind made the analogy that verilog is to Bluespec as assembly is to Java. I agree with this. Bluespec abstracts away a lot of low-level language features just as Java does to assembly; it makes accessing some of those low-level features possible, but inconvenient. The second part of his argument is that nowadays, we don’t care about how many registers our CPUs have if we write in Java, but we can still produce code that does things in a reasonable amount of time thanks to the fact that the tools that translate what we design into something machines understand are very good. I do not believe that this same philosophy ports to hardware. Hardware design is very different than software design. The reason this argument doesn’t hold in my opinion is that for the vast majority of hardware design cases, you are going to be pushing the very limits of what the hardware has available. In fact, given that microprocessors are getting better and encroaching on territories that FPGAs typically held, the remaining territories are areas where you’re trying to do super-optimized stuff. That doesn’t happen in software. In software, the majority of the use cases make it good enough to use a high level abstraction to accomplish things. In hardware, the majority of the use cases necessitate that you do a lot of low-level optimization. This is the fundamental fallacy of Bluespec, in my opinion — it does not properly reveal lower-level techniques for optimization.
Nevertheless, I had a lot of fun in this class and I learned a lot. My work with Bluespec really got me thinking about how I could design a hardware description language that could utilize some of the philosophies of cleanly defining state transitions and coming up with a better way of handling the translation between numeric representations.