May 10, 2010 -- For many years, design reuse has been touted as an essential part of completing projects on-time and on-budget. This idea is not new and the expression "don’t reinvent the wheel" is used in high-tech environments the world over for very good reasons. Design reuse is typically approached either from a solely hardware (microprocessor cores, reusable IP peripherals, hardware acceleration, and so on) or software (RTOS, protocol stacks, run-time libraries and so on) perspective, but rarely both. Why is that and how can it change?
Inevitably, one engineer’s reuse ends up being another’s major headache with either the hardware or software team working around the other team’s labor-saving (for them) decisions. The idea of design reuse is certainly attractive to all of us but using a "standard" solution that merely forces the "custom" development into another part of the project is not the solution. What’s needed to maximize the benefit of IP reuse is an approach that considers both hardware and software to be equal partners while never requiring either side to understand the other’s implementation details.
Such an approach requires that defining IP for hardware functions is done in concert with software and development tools so that interfacing between an application and hardware is immediate, portable, and efficient with no need to look "under the hood." A practical way to achieve this is to include software APIs with hardware IP with the result that designs are easier to get running, faster to complete, more maintainable, and more portable.
What? No software!
The problem, in short, is that hardware IP suppliers don’t include software to interface to their cores and software vendors leave the job of interfacing to the hardware to the customer. Go check your IP vendors' sites for software packages to complement their cores. Who has Ethernet IP with software to make it run under the popular RTOS and stacks? Who even makes recommendations, or proposes best practices, to guide the software engineer who needs to interface to these cores (that they didn't have a say in selecting)?
It’s the same now as it has always been – "here’s your data sheet, there’s the software section and, yes, it’s a bunch of registers with really long names in capital letters to make them look important. Don’t call us when you cannot get the right information out of the CORE_STAT_BITS field of the CORE_BASE_TX_STATUS_REG because you forgot to enable the packet de-atomization regulator feature in the (optional) CORE_FEAT_OPT_EN_REG register."
It's also fairly common that register names are as cryptic and implementation-specific as those above. I salute the software geniuses who can decipher this stuff and make things work. It’s amazing that hardware designers aren’t attacked more often by irate software engineers. More problematic, however, is that the lack of software in their "whole product" is based more often than not on the fact that the software hasn’t been written. Of course, software does exist that interfaces to the core so that the device developers can test and achieve compliance certification for the device. The software is just not distributed because the vendor lacks the bandwidth and expertise to support it in all the environments to which their customers will apply it.
The software side is not much better. The problem with software is that it has to work for all the different hardware implementations. The software supplier has to figure out the registers and bits and "enable this, disable that" hocus pocus for all the IP it wants to support. Inevitably this leads to a dilution of the supported IP, with only the most popular working "out of the box" and the rest being supported by the catch-all hardware abstraction layer (HAL).
This is when software vendors begin staring at the floor and mumbling that your core is not supported but that, "All you need to do is implement the hardware abstraction layer. It’s a thin layer of code that you write in C. Just a few simple APIs really." This is when developers should reply, "That sounds great, so when will you have it ready for me?" Seriously, as an industry we have to stop accepting the "we haven’t done it but it is really easy" line.
The problem with standards
There's a gap between hardware and software that has existed for as long as I can remember and shows little sign of closing. I don't believe this is due to a lack of will. Hardware IP and software vendors do collaborate regularly but the solutions seem to always be one-off solutions that aren’t easily transferable to new platforms, CPU architectures, or operating systems.
Indeed, many hardware-focused web sites have added a standalone section on software IP to complement their traditional standards-based scores and verification IP. This is definitely a good thing and working in the right direction but, in my view, should never be necessary. This is because it still leaves the hard work up to the software engineer. To be really useful, the software should be coupled with the core, not tacked on as an after-thought.
One approach might be to develop a standard to address this issue. The problem with standards is that there are so many to choose from. Worse, they change over time (Wikipedia lists about 40 versions of IEEE 802.3 (Ethernet)). Worse still, they always leave little gaps that the authors consider (or convince themselves) to be harmless "implementation details" that are precisely the areas that create a miserable experience for software developers.
A tool for all designers
The real answer lies in the tools designers use to create IP. Whether you're designing for ASIC or FPGA, the tools offer a similar array of amazing functions, except one – the ability to encapsulate software along with the IP.
You can develop the IP block in Verilog or VHDL (or even as a schematic), you can synthesize it, simulate it, verify it, embed assertions in it, write test benches for it, write verification IP for it, document it, then wash it, wrap it in pretty paper and put a bow on it. This is all fantastic stuff but you can’t attach an API to it.
Why not? Why can’t the IP development tools, which are often the same tools used by the consumers of the IP, include a feature to specify APIs with the IP that become real APIs when the user instantiates the block in their design?
How might such a feature work? An example of it in action is provided by Cypress’ PSoC Creator, an Integrated Development Environment (IDE) that supports the PSoC 3 and PSoC 5 devices. Because those chips comprise embedded microprocessors (8051 and ARM Cortex M3) along with a programmable digital array, the tools need to combine hardware blocks, or components, with software APIs to simplify the software development and accelerate design.
Developers begin by creating designs using a schematic capture interface where users can drag in components from a catalog of analog and digital components. A component comprises a symbol (which is the visible representation in the schematic), an implementation which could be another schematic (designs are hierarchical), an HDL such as Verilog, or even a complete implementation in software. This is all standard fare but most components also come with a software API tool. When the user builds the design (synthesis followed by place and route) each component has APIs generated based on the name of the instance in the design and the parameter settings selected by the user.
A UART design serves to make the point. The UART component needs to be parameterized so that important setup choices, such as flow control and baud rate, are easy to make while allowing unnecessary functionality to be selectively omitted from the implementation.
In Example 1 below, two UARTs are contrasted, with the second one only supporting polled output and, as a result, using considerably fewer device resources. Applying the same approach to software, the APIs generated are tailored according to the same parameters. First, each instance of the UART component has a unique name that is pre-pended to the API names to create a unique set of APIs for all UARTs in the system. All components have a Start and a Stop API and so, for an instance named "UART_1", the tool always generates UART_1_Start( void ) and UART_1_Stop( void ).
 |
Example 1. In this example from Cypress’ PSoC Creator, UART_1 is a full implementation supporting Tx and Rx in interrupt mode with a hardware Tx enable output (for RS-485). UART_2 is a simpler (smaller) implementation that simply streams out data in polled mode. In the latter case, the unnecessary APIs for reading data controlling interrupts, checking Rx status and buffer management are not created by the tool, reducing confusion and errors. |
The second example below is a UART component from PSoC Creator. From the bottom up, there is a documentation file (.pdf), a symbol file (.cysym) to represent the component in schematics, a schematic (.cysch) for the implementation, then a folder of header (.h) and source (.c) files for the APIs.
 |
Example 2. An example UART component from PSoC Creator. |
The user’s parameter selections are used to modify the remaining APIs. For example, because this UART does not support input, the APIs to support this function (GetChar(), GetRxBufferSize(), ClearRxBuffer(), ReadRxStatus(), SetRxInterruptMode(), EnableRxInt() and so on) are excluded from compilation by "#if" controls on the parameter setting. This is useful since if the user tries to call an API that is intended for functionality that is not present in the implementation, the compiler cannot resolve the address of the missing function and the (hard to fix) run-time error is avoided.
The parameterization can be more fine-grained than this. In the example, the UART is polled and so, while the PutChar() and ReadTxStatus() functions are still generated, there are no routines to enable or disable the interrupts.
Developers can modify the output functions based on the target CPU architecture and tool chain. For example, a PSoC 3 has an 8-bit 8051 core whereas the PSoC 5 family uses a 32-bit ARM Cortex M3. The tools for these architectures could not be more diverse and pose a mine-field of integration and porting challenges.
Cross-architecture support is handled in the same as parameterized functionality. The UART in a PSoC 5 has a larger buffer and so the return values from GetBufferSize(), for example, are selectively chosen to be a char or short value (1-255 on 8-bit, 1-65535 on 32-bit devices) and the generated code remains efficient and compact on the 8051.
Tool chain specifics can be abstracted away with macros too. With interrupts being a common area of divergence from the ANSI standard, especially on 8-bit devices, wrapping the declaration and definition of the functions in macros creates a method of writing compiler-independent interrupt routines that are easy-to-use and safe.
Finally, as shown in Example 3, using macros to define interrupt routines allows the same code to be used on any number of compilers . The macros are defined in a system-wide header file, and in this case the 8051 compiler (from Keil) recognizes the define "__C51__" and the interrupt keyword as appended to the function definition. For the ARM GNU compiler (from CodeSourcery) the "__GNUC__" define ensures that the unnecessary keyword is omitted.
 |
Example 3. Using macros to define interrupt routines allows the same code to be used on any number of compilers. |
The end result of this simple extension of the tools used to create and use hardware IP is that the experts get to write the HAL. This is preferred since as the developers of the IP they really should know best how to drive it efficiently and safely.
An industry shift?
The key benefit of incorporating software APIs with hardware IP is that the most common errors – and often the most difficult to fix – can be minimized, if not completely avoided. The engineer that is interfacing to the core does not have to be an expert on its implementation. This is great news for software engineers tasked with system bring-up because they were often not on the project when the core IP was selected and laid out in the design.
As programmability, with all its benefits and opportunities for innovation, continues to grow into a staple of our designing lives, software will increasingly become the key product differentiator in product selection. Tools that combine IP with portable, consistent software interfaces are necessary to support and achieve the many benefits of design reuse. IP suppliers and tool vendors who ignore this growing need do so at their peril.
By Mark Saunders.
Mark Saunders is a Senior Product Marketing Manager at Cypress Semiconductor Corp. He has a First Class degree from the University of Leeds, England, and over 20 years of experience in embedded software and intellectual property (soft IP). He specializes in the development, support and marketing of embedded software tools, real-time operating systems, protocol stacks and middleware.
Go to the Cypress Semiconductor Corp. website to learn more. |