Not necessarily, I am a beginner in hardware design, and I am creating a new programming language and IDE for hardware design.
> The academics who trained us at uni had never worked in industry and had no real clue. Hence we had to learn the real stuff from the older guys.
I can relate, this is by talking to older designers that my co-founder and myself learned that CDC is a big thing to address for instance. But a lot of times we were just dismissed as too young and inexperienced. Anyway, I'm curious, in your opinion what would be the biggest pain points in digital hardware design today?
Good point about the reasons of productivity leaps. Funnily enough, I recall that one of the main selling points of Java was portability (the famous "Write Once Run Everywhere"), even though C was already supposed to be portable; but the environment wasn't, and you still had to develop OS-specific code.
Anyway, yes I agree the ecosystem is key. This is why a lot of new languages are either running on the JVM (like Clojure and Scala) or are interoperable with C (like Rust and Nim). In other cases, languages have managed to create an entire ecosystem very rapidly (Node.js and Javascript in general, Ruby and others).
> The thing is that with modern hardware, even toy software projects are quite usable
You're right. I must admit I'm not a big fan of this "throw more at the problem" approach, and I wonder for how long this approach will work. After all, Moore's law is slowing down, as the unit cost per transistor has stopped decreasing after 28nm.
> but this isn't the case with hardware design.
Yes, for one because if you design hardware that is sub-optimal, in other words that requires more transistors, that translates into higher costs, and lower margins. That's some powerful incentive IMO. Not to mention that if the hardware is not powerful enough, the toy software projects that you mention will have trouble running ^^
Therefore I think a central question is the loss of performance compared to the gain in productivity. A naive translation of C to assembly leads to disastrous performance. For years (decades?) people had to resort to assembly for speed-critical routines, and you can still find assembly in video decoders for instance. But the productivity is so much higher than the loss of performance is acceptable.
To whomever downvoted this: would you mind telling me why? Have I offended you in some way? Is it because of the criticism of the hardware industry? Or the sarcasm?
That's like saying that buffer overflows are not due to how strings are represented in C. Yes a bug is the programmer's fault, but languages can make it harder to have bugs in the first place (for instance you can't have buffer overflows in any other higher level language than C).
In the case of the hardware industry, we see a language with a weak type system (Verilog). So the "solution" is to use lint tools to check that your design is properly typed. Similarly, nothing in VHDL/Verilog prevents you from accidentally creating latches, or crossing domains badly, or many other small bugs. So again, the "solution" is to do extensive verification. That's the Haskell VS Python debate: you can either make it impossible to have a certain class of bugs (and detect them very early), or you can just write a lot of tests (which, in the case of hardware, take forever to run).
The same logic extends at a higher level. You can have a language that models common patterns (like a synchronous loop, a "ready before valid" port) so you can reduce the amount of verification needed because you don't need to always re-verify everything. One could even argue that having such higher-level mechanisms would also make static verification easier, since you might reason in terms of transactions rather than updates to registers.
> For an engineer it does not matter about the language that describes the circuit. [...] Typing it in is the easiest part.
Well... once upon a time, people were writing software with assembly, and they probably didn't care about the number of lines either. After all, typing was easy, in fact the only problem was just porting your program to a different architecture :-)
You talk about the complexity of a SoC, and you are right it is complex. But software is complex, too: an application relies on hundreds of millions of lines of code, counting everything between the hardware and the application (OS, network stack, HTTP server, all libraries, database, etc). So how do software engineers manage all that? They use better languages than assembly. Because what matters is the performance/expressiveness ratio (which is why C is still relatively popular) and how hard it is to shoot yourself in the foot (which is why C is not as popular as it once was :D).
> They are all toys aimed at newbies. They address problems that are no problem at all to a qualified engineer in the profession.
I think this kind of attitude is one of the main problems of the hardware design industry (the other one is the conservative mindset). Today's beginners could be tomorrow's hardware designers, instead they switch to software because the culture is much more open and friendly. Besides, you know what they say about asking users what they want: if Henry Ford has asked his customers what they wanted, they'd have asked for a faster horse ;-)
> Reading from a port twice seems to trigger a clock cycle (did I get that right?)
You did! It is by design that reading from the same port twice will trigger a clock cycle :-) There are several reasons why we did it this way. First, having to always explicitly declare a new clock cycle (rather than having it inferred) is kind of ugly, because your code is full of "fence;" instructions. The second reason is that we thought this would actually prevent bugs ^^ (the third is for symmetry with writes I think)
The thing with Cx is that, unlike VHDL/Verilog, reading a port can mean more than accessing a single signal, and similarly writing to a port can be more than writing a single signal. For example "sync" ports have an additional "valid" signal that is set to true for one cycle when data is written to the port. This is very handy, allowing synchronization between tasks (read becomes blocking) and is useful as a control signal (the "valid" signal serves as the write enable on a RAM for example). We also have a "sync ready" that adds an additional "ready" signal computed asynchronously and again useful for back-pressure control in pipelines, FIFOs, etc.
That's the beauty (and sometimes the curse) of hardware design: it doesn't need a processor to run. You essentially describe an electronic circuit, and "program" (configure would be more appropriate) an FPGA to act like the circuit you described. A circuit can be as simple as you want (like a sequential counter) or very complex (people have implemented entire H.264 and HEVC decoders in hardware).
This is so powerful that in fact you can even describe your own processor, and prototype it on an FPGA for testing.
Interesting, I feel like you would like what we've done with the Cx language at Synflow. Probably the exact opposite of CλaSH, the language is sequential imperative (C-like even) and focuses on making the sequential part easier (Cx still has first class support for parallel tasks and hierarchical descriptions though). You have synchronous "for", "while", "if", this kind of thing :-)
http://cx-lang.org
Enjoy!
Hard to say, it depends on what you consider better. It certainly is more concise than the equivalent Verilog (just like Haskell is more concise than pretty much any language I know). This seems especially true when you want to describe repetitive structures (such as their FIR filter).
CλaSH also has a much better type system than Verilog (again, thanks to Haskell), but if you wanted a good type system when describing hardware, you might as well just switch to VHDL ^^
My concern is with the description of state machines. You need to specify if you want a Mealy or a Moore machine, something that is usually implicit. And you're still describing the transfer function between states; CλaSH does not seem to allow you to describe your program in a structured way (such as loop until x becomes true, wait for 3 cycles, read z, while z > 0 decrement z, etc.)
I agree, it is an interesting idea. I suspect that just having "Haskell" got the link a lot of upvotes :-) As stated on the "Why CλaSH", the advantage is obvious for combinational circuits. But it doesn't seem to help much for synchronous logic (which arguably represents the majority of hardware designs). You'll still be writing everything as "how to update register X in state S".
How well HLS does highly depends on the source code (this is in general and not specific to Vivado HLS). If your code is a simple loop over an array and you add a vendor-specific #pragma directive (such as #pragma unroll) the tool will unroll your loop and extract the parallelism from there. This actually works quite well in practice for regular DSP code (like FIR and FFT) and floating point. Anything else is another story though.
The thing is that unless you're writing your code as the tool expects it, with the proper pragmas etc. there's no way it can be transformed to fast hardware. A way around that is for vendors to ship "customizable IP" kind of like Altera's Megafunctions... so much for portability and high-level.
I'm not sure which tool OP is referring to though, I remember Altera had a C2H tool that they discontinued in favor of their OpenCL SDK.
@gothenburg @mng2 I get that you think it's not useful or even it's crazy, especially as both of you seem to be seasoned hardware designers. But as a software guy myself, there's nothing I have found more horrible when learning to write some VHDL than finding out what was allowed in synthesis, what was tolerated but not recommended, and what was legal VHDL but could never synthesize. Things like automatically inferred latches because of local variables, multidimensional arrays supported but not always (vendor-dependent), loops that work for combinatorial logic only, "wait" that are not permitted (or only in vendor-specific ways), etc.
In Cx you can't create latches, loops work for combinatorial logic and synchronous logic alike, and all in all there are no unsynthesizable constructs. Finding out if a piece of code will result in unacceptable performance is a different problem, I hope to have the compiler kind of "guide" you on this kind of things.
Really? Aren't they using VHDL generics/Verilog parameters?
Cx supports specialization of entities with this kind of semantics, so you give an instance parameters and the compiler generates specialized code (so there's no more need for Perl scripts thankfully ^^). Right now you can't enable or disable things, but this is something that would be excellent: modify the hierarchy, add or remove ports, all depending on which flags the entity was instantiated with.
As I explained in another comment a few minutes ago, we're not so much about syntax as we're about better semantics and higher level description (I agree this isn't very clear on the website). Your remark about the ecosystem is perfectly right, and this is what makes EDA a tough market.
I don't know enough about verification to comment. I know SystemVerilog is very powerful but very complex, I've read about UVM and stuff, some people use SystemC. I wonder how they even manage to get hardware validated!
Yes it is still in use, and the simulation capabilities are quite advanced! It remains a HDL, better than VHDL and Verilog, so you still have to worry about resetting, clocks and state machine.
Just a word of caution the cycle accurate simulator is still a bit experimental (don't use big numbers, and bit accurate signed arithmetic is not finished yet... we're working on it)
That's a very good point. In fact the main difference in semantics is that Cx code is structured. Sure in VHDL/Verilog you have functions and if statements and loops. But they can only be used to describe combinational logic. There is a chasm between synchronous logic (everything in a big switch/case) and combinational statements.
Cx supports functions, if and loops for both combinational and synchronous logic. You can have a function that spans over two cycles. You can give parameters to this kind of function just like in software, except that in the end this is all inlined and the state machine is flattened.
The language encourages a higher level of abstraction where you think in terms of blocking reads and data availability rather than "is my signal true". The best is that this can be extended just by changing the port signature, for example to provide rendez-vous style communications (we call it "sync ack" but they're not implemented yet), whereas in HDL you'd have to write a lot of boilerplate code.
Another property is that there is no synthesizable subset in Cx. As far as I know, this is very rare in languages for hardware design, but the language is entirely synthesizable. You never have to think about synthesis versus simulation. Exactly like in software, nobody ever wonders if they can write code that won't run on the processor :-)
And for the example you mention, this is another interesting feature of the language. Because we support sequential loop constructs etc. you can actually write code that works and synthesizes pretty easily, albeit it is slow. And then you can produce a derived version that is optimized :-)