I recent wrote about the similarity in software and hardware design, as they are both performed by writing code in a high level programming language. My colleague Richard Vlamynck, wrote to me, suggesting that he might be able to usefully expand on this topic. He is an unusual guy, even within Mentor Graphics, as he is a modern day “Renaissance man” – he has a very good understanding of both hardware and software design. So, I was very pleased to accept a guest posting from him …
I’ve been following Colin’s blog and especially interested in the issues, answers and comments regarding programming languages for embedded systems. So, when Colin mentioned VHDL hardware description language (HDL) a couple of posts ago, it caught my attention and made me put down my xacto knife and roll of rubylith just long enough to bring you-all up to date on what I consider to be an exciting development in embedded systems programming, namely the System-C library for hardware/software co-development.
Let’s say that you were tasked with building a module to be integrated in a system on a chip (SoC). For the hardware flow, you would first pick a hardware description language such as Colin’s favorite (VHDL) and then create the hardware design by wiring up some registers to hold the incoming and outgoing data, along with the logic and clock circuits to perform the actual functionality of the device.
After designing your hardware block, then you would use a hardware synthesis tool (such as Design Compiler from Synopsys or Precision from Mentor Graphics) which, in short, wires up all the transistors together as you described in your VHDL program.
A hardware description language is similar to a software description language, except that it allows for concurrent programming. A hardware description language, such as VHDL, allows you to have more than one main() function in your program. Think about it for a moment, if you have multiple main() functions running concurrently, then you’ll need to add syntax and semantics to your programming language to synchronize and handshake among all the functions. This is exactly how VHDL differs from a conventional software programming language.
Let’s say that you’ve created your device using VHDL. Next, you are also going to perform some system level analysis to see just how the entire SoC is going to perform. You could wire up all the rest of the SoC modules (ie. in addition to your device, there may also be a CPU block, a USB controller block, a video controller block, an Ethernet controller block, a UART block etc. – you get the picture.)
This means that you’re going to need a simulator that understands how VHDL operates and can simulate the entire SoC as it’s running. The VHDL simulator know about synchronous and asynchronous clocks and reset signals. The simulator has to know how to handle positive and negative pulse edges on wires and the delay of those signals as they propagate down the wires.
The downside to a VHDL simulator is that while it is very accurate in modeling the actual clock cycles of your device, it’s also very slow when you try to run a huge design such as the entire SoC. That is to say, the actual clock speed of an embedded ARM SoC that’s in your cell phone might be 300MHz, but when you’re the cell phone designer and you run the cell phone SoC HDL in a simulator, you will be running a hundred or a thousand times slower. It’s not practical to do software development on that type of simulation engine.
But there’s a faster way to simulate a SoC, and that’s to simulate not the actual transistors and gates, but to simulate the behaviour of the SoC. So if we had a behavioural model of the SoC written in some high level software programming language, then we could start to explore in real-time the interaction of the software stack that’s going to be running on our SoC.
So now, I will write a description of the behaviour of our device in the c-language. The advantage is that now I can test it much faster and easier using the wealth of standard software programming facilities that are mature, stable and well proven. I don’t have to worry about clocks and resets and wires when I’m programming in the software world. The disadvantage is that now I have to maintain two different models of the same functional block.
Is there some way to get the best of both worlds? What if I could create a behavioral model of a functional block in a software programming language and that same model could be fed into my hardware synthesis tool to create the actual gates and transistors?
The paradigm that I’m looking for is System-C.
System-C is nothing more than a library that you use with your existing C++ development tool kit. Simply stated, System-C is just another set of classes and macros, and in this case, it lets you simulate concurrent processes within a single program. Another advantage to System-C is that it offers a synthesizable language subset. That is to say, some, but not all, System-C programs can be synthesized into real hardware. This means that the judiciously written System-C program can run in a software simulator, or it can be turned into actual silicon gates and transistors.
In a future post, we’ll look at some real world examples of using SystemC.