The escalating use of C-based design and synthesis enables software to run faster, system bottlenecks to be captured and accelerated and very complex SoCs to be designed faster, with lower risk and at a lower cost. The level of complexity tackled by C-based design is no longer rare. The Semiconductor Industry Association (SIA) roadmap forecasts a relentless increase in design complexity. Moreover C-based design and synthesis is all the rage, Gartner's Gary Smith and other key industry analysts laud it. There are some 20+ (and growing) small to medium sized EDA companies leading the development of C-based design and synthesis and EDA's 'big 3' now support C-based flows through products, services and IP.
So is this a revolution, a radical change? Well, no, not really.
The technology and associated challenges have been around for a long time. It is more than eight years since Celoxica designed its first C-based design and synthesis tool into a high-energy physics project. The end product was a real-time massively parallel data processing and analysis engine.
What has changed is that we now have agreed terminology and industry acceptance for an IC design paradigm into which these methodologies, tools and languages best fit -- the Electronic System Level (ESL). Add to this the cold reality of very complex SoC design, performance/power mismatches, timing convergence and ever-decreasing geometries and you have great need for lots of people developing C-based ESL products and lots of engineers using them.
What's more, there is a wide belief that, from a descriptive point of view, C is most suitable language for ESL design. This is important, because it is a key differentiator between today's ESL solutions and previous attempts at higher-level design that were grounded in behavioral HDLs. The C language is almost ubiquitous in design communities. Designs are often specified in C/C++, because some problems are just better expressed as a software algorithm and C reference designs are widely available. However, some users remain skeptical about the role of C in hardware and SoC design, particularly about the impact of trade-offs at the levels of abstraction between behavior and the transistor.
The pros and cons of designing chips at higher levels of abstraction are very well documented, very well understood and pervasive within design circles. The intention here, then, is not to revisit this debate, but to offer an implementation perspective on why the C language, originally developed for systems programming really does work for hardware and SoC synthesis.
The focus is on supporting verification through early rapid prototyping, accelerating system bottle-necks and completing the ESL flow from concept through synthesis to implementation.
Figure 1: Top level SystemC synthesis flow
with the Agility Compiler
Modeling and simulation
Before looking at C-based synthesis and implementation, it makes sense to highlight modeling and simulation, the springboard that took C into hardware and SoC design.
These are best articulated using Transaction Level Modeling (TLM) as the framework. With enough detail TLM describes hardware and software together. It separates functional units from communication, it abstracts interfaces with an emphasis on functionality of data transfer and it may be untimed, timed or bus-cycle accurate.
The design trade-off here can be crudely summarized in terms of speed against accuracy. At the behavioral level, simulation speeds are many orders of magnitude faster than at the Register Transfer (RT) level. The trade-off for speed is a reduction in lower-level detail.
At the RT or indeed the gate level, simulations are feature-rich and highly accurate. But the time taken to simulate modern SoC designs at this lower level means the process is no longer commercially viable.
Within the resulting trade-off, TLM balances the need for speed with the demand for detail and accuracy. Traditionally it is at the close of this stage in design that the emphasis would shift to synthesis and implementation; but with C-based design this is not necessarily the case.
A fundamental advantage that C-synthesis offers the designer of complex ICs is not only a faster route to physical implementation using familiar ASIC/ SoC tools and flows, but the ability to support verification and simulation with early rapid prototyping in programmable logic. Using C-synthesis, designers are able to implement their design ideas and models in working silicon much earlier in the design flow than was previously possible. This yields accurate performance metrics and timing information from working prototypes that are fed into the overall design and verification framework. Of course, the capability to directly target programmable logic is equally relevant and compelling where the FPGA or programmable SoC devices are designated for production.
We should first address perhaps the most contentious issue surrounding synthesis from a C-based ESL flow; today, you cannot synthesize pure, untimed C or C++ to an efficient hardware implementation or RTL description.
While it is true that C and C++ contain no notion of hardware, the designer can quickly overcome this by adding the necessary intelligence to achieve and optimize the quality of results. C-synthesis, with underlying hardware semantics, is 100% real and efficient when it is predictable, deterministic and under the designers direct control.
The flip-side is compiler-determined concurrency where there are fundamental limits on how much concurrency can ever be found by a compiler . Basing synthesis on heuristics and "magic under the hood" is just too risky for complex IC design.
The synthesis of an untimed algorithmic description of a desired behavior that then creates an efficient hardware implementation of that behavior remains elusive; it is still the "Holy Grail" of computer science.
Challenges and approaches to C-synthesis
There are five fundamental challenges to overcome before you can generate an efficient hardware circuit from a C description. And the corollary of these multiple challenges is multiple solutions based on different approaches of how to solve them. These challenges are:
1. Communication -- To tackle communication you can preserve the C-like model for describing communication, or add in additional communication mechanisms and additional types. Channels are an example and used in SpecC and Handel-C to communicate between and synchronize parallel processes.
2. Concurrency -- There have been several attempts to enable compiler-determined concurrency, though this approach still remains to be proven both in research and production design flows. Alternatively and in much wider use, concurrency can be described in an explicit sense. Explicit control over concurrency in a C-based language can be simply enabled by the designer using the parallel, 'par' statement. Again, used in SpecC and Handel-C, the par statement allows concurrency in a design, with assignments in a par block being executed in parallel. In the hardware implementation the tasks are executed simultaneously because each operation has its own dedicated hardware resources. In SystemC concurrency is achieved with threads communicating with one another via channels (most commonly signals for synthesis).
3. Timing -- This can be handled by the explicit inclusion of timing in the language, or by putting in place a rule-based system against the semantics of the language. Instead, a compiler-determined timing approach using constraints could be used. With timing being a critical element in the success or failure of any design, rule-based or explicit control over timing dominate the different approaches. In SystemC the designer using the "wait" statement can explicitly control timing, and in Handel-C a rule-based system is used where each variable assignment and "delay" statement takes one clock cycle to execute.
4. Types -- Here, the engineer can add annotations into the C files, explicitly inserting hardware data types. Alternatively, designers can add hardware data types as classes in C++.
5. Meta-data -- The engineer must be able to direct a synthesis tool to share resources and provide direction for the implementation of those resources into the target silicon. You can annotate the source code with additional constraint files or enter annotations through GUI-based systems.
To better understand the different approaches to these challenges the accompanying code examples and illustrations highlight how elements of these different approaches can be implemented. Several languages and techniques are used.
This constraints approach uses labels or tags inside the code to direct the synthesis. The example code in Figure 2 is a fragment of HardwareC, a language that supports both declarative and procedural semantics. It has a C-like syntax and is extended with a notion of concurrent processes, message passing, timing constraints via tagging, resource constraints, explicit instantiation of models, and template models.
Figure 2: HardwareC code fragment
In the code fragment you can see three labels - '1', '2' and '3' - supported with constraints to control blocks of code in terms of timing.
SystemC: Explicit control and C++ -based
The code in Figure 3 is a fragment of SystemC, a language that provides hardware-oriented constructs within the context of C++ as a class library implemented in standard C++. Its use spans design and verification from concept to implementation in hardware and software.
Figure 3: Multiplier template described in SystemC
The code is a multiplier template and is an example of a pipelined design in SystemC. The multiplier template is intended to be used inside a thread, or a clock thread that is sensitive to a clock edge.
The approach used in this example is an explicit description of concurrency. There are explicit clocks in the timing described using wait statements, and the SystemC data types sc_int and sc_uint are used.
Handel-C: Explicit control, rules-based timing and additions-based
Handel-C is a programming language expressly designed for the compilation of high-level C descriptions to hardware. It is synthesizable ANSI C with extensions to take advantage of hardware architectures.
The code fragment in Figure 4 again shows a multiplier template. In this approach the concurrency is again explicit using the par (parallel) statement. Timing is controlled by rules within the language and there are additional types and communications (e.g. the chan (channel) statement).
Figure 4: Multiplier template described in Handel-C
Each different approach to solving the challenge of C-synthesis has its merits, its supporters and its critics. External constraints can allow the user to leave some elements of the source code untouched, but they are proprietary to particular tools and lock designers and the product into a single vendor. The designer may also lose control over a design by relying upon 'under the hood' technology to make what they hope is the correct decision.
More explicit control allows intelligence to be input into the code by the designer, with the design more tuned and optimal for implementation. In this way the results are more predictable and fundamental control over critical design areas remains firmly with the developer. The consequence of course is that the designer must have the knowledge and expertise to introduce that intelligence in the first place, but this ensures quality results and in the end is neither more difficult nor more manual than the writing of constraints.
Design complexity and commercial necessity have driven C-based ESL design into the mainstream. Celoxica's approach, developed over the last 15 years is based on a provable, predictable and deterministic approach to behavioral design and synthesis based on the C language and level of abstraction. Explicit control over the design and synthesis process is used wherever it makes sense and is practicable to do so.
This family of commercial grade C-based behavioral design and synthesis tools has been available for eight years, and it can therefore also be said that the deterministic approach adopted by Celoxica and others is sound and proven.
Within the Celoxica model, support for IC design is provided via the synthesis of either SystemC or Handel-C to IEEE compliant VHDL and Verilog. Uniquely Celoxica's tools support direct compilation of a C-based design to device optimized programmable logic for production and ASIC/ SoC prototyping.
C-based design and synthesis closes the ESL loop and helps deliver a major step forward in design productivity, efficiency and effectiveness. There are different approaches, languages and tools emerging. Which will dominate? It is too early to tell, but it is likely that complementary solutions will coexist in the future, just as they do today.
Acceptance and usage of C-based design and synthesis is following the classic technology adoption curve. A few years ago I was commonly asked "Which EDA vendors are supplying C-based ESL tools" and "which companies use C-based ESL tools and methodologies in their design flow."
Today, the questions have gone full circle; today I'm asked "Which EDA vendors are NOT supplying C-based ESL tools" and "which companies DO NOT use C-based ESL tools and methodologies in their design flow." The answer is not many.
By Chris Sullivan, Director of Strategic Alliances at Celoxica, Ltd.
Go to the Celoxica, Ltd. website to learn more.