How to use UML in your SoC hardware/software design: Part 1From determining the hardware/software partition to meeting performance and cost objectives, the job of building systems on a chip has never been easy, and with ever-increasing demand for more functionality packed into smaller spaces consuming less power, building systems on a chip is unquestionably becoming more complex every day.
Add to this the desire to shrink development cycles and reduce the overall cost of the system, and you have an acute need to raise the level of abstraction and reduce unnecessary miscommunication between hardware and software teams.
To meet this need, several specification languages have been proposed such as Handel-C, SystemC, and so on. These languages unite hardware and software to some degree, but C is at such a low level of abstraction that software engineers have begun to move away from it as a specification language and use a more abstract modeling language, namely the Unified Modeling Language (UML).
As with most of the hardware-oriented C variants, one solution to the problem of taking a software-oriented language for use in SoC is to add hardware features to it. The same has been proposed for UML , but we propose the opposite: use only the minimum necessary to specify system functionality.
We then use model mappings, coupled with marks that indicate which mapping rule to apply, to translate the application model into hardware and software description languages. This approach enables a major simplification of the use of UML in SoC, and corresponding simplification of the work of SoC developers.
The State of the Practice
SoC design can be broken down into three important tasks:
(1) partitioning the design
into hardware and software segments,
(2) understanding the hardware/software interface; and
(3) integration of the hardware and the software.
Partition: At the beginning of an SoC project, it is common for the hardware and software teams to build a specification, usually in natural language. This defines a proposed partitioning into hardware and software so the two teams, with different skills, can head off in parallel.
Verifying the hardware/software partition requires the ability to test the system, but it takes months of effort to produce a prototype that can be executed.
Yet we need to execute the prototype before we will know whether the logic designers and the software engineers have the same understanding of the hardware/software interface. We also need to run the prototype system before we can measure its performance, but if the performance is unacceptable, we must spend weeks changing the hardware/software partition, making the entire process circular.
Interface: The only thing connecting the two separate teams, heading off in parallel, each with different skills, is a hardware/software interface specification, written in natural language. Two teams with disparate disciplines working against an ambiguous document to produce a coherent system.
Sounds like a line from a cheap novel.
Invariably, the two components do not mesh properly. The reasons are myriad: the logic designers didn't really mean what they said about that register in the document; the software engineers didn't read all of the document, especially that part about waiting a microsecond between whacking those two particular bits; and of course, the most common failure mode of all, logic interface changes that came about during the construction of the behavioral models that didn't make it back into the interface specification.
Integration: So what's a few interface problems among friends? Nothing really. Just time. And money. And market share. We've been doing it this way for years. It's nothing a few days (well, weeks) in the lab won't solve. Besides, shooting these bugs is fun, and everyone is always so pleased when it finally works. It's a great bonding experience.
Eventually, the teams manage to get the prototype running, at least well enough that they can begin measuring the performance of the system. "Performance" has a number of meanings: Along with the obvious execution time and latency issues, memory usage, gate count, power consumption and its evil twin, heat dissipation, top the list of performance concerns in many of today's embedded devices.
There's nothing like a performance bottleneck to throw a bucket of cold water on the bonding rituals of the integration heroes. Unlike interface problems, you don't fix hardware/software partition problems with a few long nights in the lab. No, this is when the engineers head back to their desks to ponder why they didn't pursue that career as a long-haul truck driver. At least they'd spend more time at home.
What Wrong with That?
The problems associated with working this way are deeply interrelated.
Partition: For the early part of the process, logic designers and coders are actually doing the same thing, just using different approaches. Distilled, we are all involved in:
analyzing, and articulating product requirements.
* Creating abstractions for solutions to these requirements.
* Formalizing these abstractions.
* Rendering these abstractions in a solution of some form.
* Testing the result (almost always through execution).
So, why can't we all just get along? At least in the beginning.
Interface: It is typical to describe the interface between hardware and software with point-by-point connections, such as "write 0x8000 to address 0x3840 to activate the magnetron tube;" and "when the door is opened interrupt 5 will be activated."
This approach requires that each connection between hardware and software be defined, one by one, even though there is commonality in the approach taken. Using a software example, each function call takes different parameters, but all function calls are implemented in the same way.
At present, developers have to construct each interface by hand, both at specification and implementation time. We need to separate the kinds of interface (how we do function calls) from each interface (the parameters for each function call) and apply the kinds of interface automatically just like a compiler.
Integration: We partitioned the system specification into hardware and software because they are two very different products with different skills required to construct them. However, that partitioning introduces multiple problems as we outlined above so we need to keep the hardware and software teams working together for as long as possible early in the process by maintaining common elements between the two camps. That which they share in common is the functionality of the system—what the system does.
A significant issue in system integration, even assuming the hardware and software integrate without any problem, is that the performance may not be adequate. Moreover, even if it is adequate at the outset, version 2.0 of the product may benefit from shifting some functionality from software to hardware or vice versa. And here we are, back at the partitioning problem.
Evaluating Potential UML solutions
Happily, the problems described above do suggest some solutions.
Build a Single Application Model: The functionality of the system can be implemented in either hardware or software. It is therefore advantageous to express the solution in a manner that is independent of the implementation. The specification should be more formal than English language text, and it should raise the level of abstraction at which the specification is expressed, which, in turn, increases visibility and communication. The specification should be agreed upon by both hardware and software teams, and the desired functioning established, for each increment, as early as possible.
Build an Executable Application Model: Indeed, the specification should be executable. The UML is a vehicle for expressing executable specifications now that we have the action semantics of UML 1.5 and its latest version, the action model of UML 2.0. This action model was expressly designed to be free of implementation decisions and to allow transformation into both hardware and software. Executable application models enable earlier feedback on desired functionality.
Don't Model Implementation Structure: This follows directly from the above. If the application model must be translatable into either hardware or software, the modeling language must not contain elements designed to capture implementation, such as tasking or pipe-lining.
At the same time, the modeling language must be rich enough to allow efficient implementations. Chief among the topics here is concurrency, both at the macro level (several threads of control as tasks or processors and blocks of logic that execute concurrently) and at the micro level (several elements in a computation executing at once).
In other words, we need to capture the natural concurrency of the application without specifying an implementation.
Map the Application Model to Implementation: We translate the executable UML application model into an implementation by generating text in hardware and software description languages. This is accomplished by a set of mapping rules that reads selected elements of the executable UML application model and produces text. The rules, just like a software compiler generating a function call in our example above, establish the mechanisms for communicating between hardware and software according to the same pattern.
Crucially, the elements to be translated into hardware or software can be selected by marking up the application model, which allows us to change the partition between hardware and software as a part of exploring the architectural solution space.
All this provides a way to eliminate completely the hardware/software interface problems that are discovered during the initial integration, and to allow us to change the partition between the hardware and software in a matter of hours.
The Key to a Solution: The Dotted
A UML model can be made executable by simply adding code to it. However, this approach ties the model to a specific implementation—precisely what we wish to avoid. Instead, we must allow developers to specify functionality without specifying implementation
How can we capture the functionality of the system without specifying implementation? The trick is to separate the application from the architecture, and this is the key to a solution. Figure 1, below, illustrates this separation.
|Figure 1. The separation between application and architecture|
The top left of Figure 1, above, shows an executable UML model. Below the dotted line we show one of a set of mapping rules that refers to simple UML elements such as class. By executing the rules automatically, we may generate code. But the key is the dotted line that separates the two parts.
The dotted line between "application" and "architecture" enables the capture of an executable application model by representing it in a simple form: sets of data that are to be manipulated; states the elements of the solution go through; and some functions that execute to access data, synchronize the behavior of the elements, and carry out computation. This dotted line, consisting of sets, states, and functions, captures the modeling language.
A selection of these simple elements makes up an executable UML modeling language. The elements are primitive enough to be translatable into multiple implementations, but powerful enough to be useful. Once we determine exactly which elements make up executable UML, we can manipulate those elements completely independently of the application details, including whether to implement behavior in hardware or software.
We take up the definition of executable UML  in Part 2 in this series: "Executable UML Models for SoC design".
This series is
reprinted in four parts from Chapter 2 of "UML
with permission of Springer.
Stephen J. Mellor, Chief Scientist of the Embedded Software Division at Mentor Graphics, is an internationally recognized pioneer in creating effective, engineering approaches to software development. In 1985, he published the widely read Ward-Mellor trilogy Structured Development for Real-Time Systems, and in 1988, the first books defining object-oriented analysis. His latest book MDA Distilled: Principles of Model-Driven Architecture was published in 2004.
John R. Wolfe, Director of Operations and Engineering for the BridgePoint UML suite at Mentor Graphics, was President and CEO of Project Technology, Inc., since acquired by Mentor Graphics acquired the company, which was focused on tools to execute and translate UML models in the context of Agile MDA.
McCausland is a Principal
Engineer, Mentor Graphics
Corp, where he is the chief designer of the BridgePoint UML Suite. He
is the creator of (to his knowledge) the very first model compiler that
translates xtUML models to behavioral VHDL.
 UML Profile for System on a Chip at OMG Web site.
 Executable UML: A Foundation for Model-Driven Architecture, Mellor and Balcer, Addison-Wesley, 2002.
resources on Embedded.com about UML and xtUML:
Executable and Translatable UML
2) Need for modeling tools rises with design complexity
3) In Focus: Unified Modeling Language
4) Introduction to UML statecharts
5) UML evolves total system perspective
6) Introduction to UML Class Diagrams
7) State machine shortcuts
8) From UML to embedded system: Is it possible?
Currently no items