The ODYSSEY Tool-Set for System-Level Synthesis of Object-Oriented Models Maziar Goudarzi and Shaahin Hessabi Department of Computer Engineering, Sharif University of Technology, Tehran, I.R.Iran
[email protected],
[email protected]
Abstract. We describe implementation of design automation tools that we have developed to automate system-level design using our ODYSSEY methodology, which advocates object-oriented (OO) modeling of the embedded system and ASIP-based implementation of it. Two flows are automated: one synthesizes an ASIP from a given C++ class library, and the other one compiles a given C++ application to run on the ASIP that corresponds to the class library used in the application. This corresponds, respectively, to hardware- and software-generation for the embedded system while hardware-software interface is also automatically synthesized. This implementation also demonstrates three other advantages: firstly, the tool is capable of synthesizing polymorphism that, to the best of our knowledge, is unique among other C++ synthesizers; secondly, the tools generate an executable co-simulation model for the ASIP hardware and its software, and hence, enable early validation of the hardware-software system before full elaboration; and finally, error-prone language transformations are avoided by choosing C++ for application modeling and SystemC for ASIP implementation. 1
1
Introduction
Embedded systems are all around us. They are getting more complex and we are getting used to using them in all aspects of our everyday life. More complex devices in lighter packages with longer battery life-time are demanded by consumers who would change their device for a new one in a few months and who expect to see prices falling everyday. Such complex embedded systems can no longer be designed in an ad hoc manner; automated design processes starting from higher levels of abstraction are essentially required. This is confirmed by emergence of Electronic System-Level (ESL) design as next level of abstraction in the move toward higher levels [1] and the studies that show current system-based design flows still incorporate several manual and time-consuming steps [2]. Addressing these requirements and shortcomings requires system-level design methodologies, to define the design flow, along with tool chains, to implement the methodology and facilitate manipulation and use of its artifacts. In the ODYSSEY methodology [3], summarized in Section 2, we suggest to start design of embedded systems from an object-oriented (OO) model and to implement 1
This work is supported by a research grant from the Department of High-Tech. Industries, Ministry of Industries and Mines of the Islamic Republic of Iran.
T.D. H¨am¨al¨ainen et al. (Eds.): SAMOS 2005, LNCS 3553, pp. 394–403, 2005. c Springer-Verlag Berlin Heidelberg 2005
The ODYSSEY Tool-Set for System-Level Synthesis of Object-Oriented Models
395
them as software running on Application-Specific Instruction-set Processors (ASIPs) customized to that embedded application. This provides embedded system designer with the reuse, flexibility, and complexity management advantages of OO modeling along with the reusability and extendability of ASIP (as opposed to ASIC) for system implementation. The methodology [4, 5] treats OO designs in general, with no specific OO language or tool in mind. To implement it, however, specific languages and tools need to be chosen. We decided to use a single language for hardware and software parts of the system so as to avoid error-prone language transformations. Such transformations comprise a well-known source of many difficulties and errors, in developing system-level design-automation tools, that arise due to semantic difference between languages as well as complicated tool operations. Further to the above single-language requirement, the chosen HDL must be synthesizable by available tools to enable us report experimental results of complete implementation in addition to simulation results. Three major alternatives were OO variants of VHDL, Java, and C++. Several extensions to VHDL exist [6, 7, 8, 9] that include OO constructs, but they differ in their interpretation of OO concepts and only a few of them provide a path to synthesis. Hardware synthesis from Java [10, 11, 12] is also reported in the literature. However, its reported synthesis tools are academic and their level of support for various language constructs were unknown to us. We finally chose C++ since it offers necessary modeling features, it is widely used by system designers for early system modeling and validation, and its SystemC class library is a synthesizable HDL that is executable and provides high simulation efficiency. In the rest of this paper, the big picture of our system-level design methodology is presented in next section. Section 3 provides our proposed synthesis flow from C++ to final implementation. Section 4 presents the details of our system-level synthesizer tools. Testing procedure of the tool and system-synthesis experiments are given in Section 5 and finally Section 6 concludes the paper.
2
The ODYSSEY System-Level Design Methodology
Our system-level design methodology, named ODYSSEY (Object-oriented Design and sYntheSiS of Embedded sYstems) [3], consists of two parts: a modeling methodology and an implementation methodology. In modeling the system-under-design, we advocate the OO methodology, while for system implementation it follows the idea of programmable platforms. The rationale behind our modeling methodology is the dominance of software over hardware in embedded systems [13] and the high reputation of OO in the software design community due to its good support for design abstraction and reuse. As the motive for our implementation method, the high cost of design along with the high cost and risk of manufacturing application-specific integrated circuits (ASICs) in today very deep submicron technologies [14] justifies our decision. ODYSSEY wishes to view the system model as a collection of concurrently communicating objects (application-level objects, not implementation-level ones). The model of computation is objects communicating through structured messages. Multiple threads
396
M. Goudarzi and S. Hessabi
of control can co-exist in the system. Guarded operations are considered for synchronization between concurrent threads. To implement such a system model, a two-level mapping is performed. First, the concurrency in the system model is mapped to a network of interconnected processors. Then, each processor is specialized to the set of objects that it is to serve by moving some functionality to hardware; we call such a specialized processor an object-oriented application-specific instruction processor, or an OO-ASIP2 . The quantum of this migration to hardware, and hence the hardware/software partitioning quantum in ODYSSEY, is a method of a class; methods assigned to the hardware partition are called hardware methods and the others are software methods. We have previously presented two architectures for an OO-ASIP [4, 15]. The latter gives a scalable efficient implementation for virtual method dispatch to hardware- as well as to software-methods and is implemented by our tool; however, it necessitates additional care during synthesis that is discussed in Section 4.2. As mentioned above, we have broken implementation of the ODYSSEY design flow into two parts: mapping the objects to the processors, and implementing the thread(s) assigned to each processor. In this paper, we present the latter where a single processor is to be synthesized and a single thread of execution is considered.
3
Single Processor Synthesis Flow
Fig. 1 shows the synthesis flow for a single-processor target. The input program is given as a set of header and program files that together define the class library as well as the main() function where the objects are instantiated and the sequence of method calls among them is specified. The entire process is divided into two layers: we consider the upper layer as system-level synthesis; this layer takes the system model and produces the software- along with the hardware-architecture in a mix of structural and behavioral modeling styles. The lower layer is considered downstream synthesis; it takes the above-mentioned hardware and software partitions and produces gate-level hardware and object-code software. We focus on the system-level synthesizer in this paper. Downstream synthesis uses traditional tools and is not of particular interest here. It is noteworthy, however, that since we pass the hardware partition directly to downstream synthesis (so as to take advantage of the available SystemC-synthesis technology) the subset of C++ constructs that such tools accept defines the synthesizable subset that our tool allows in method code. In system-level synthesis (the part above dashed line in Fig. 1), the input program and class library are parsed and analyzed to extract class-inheritance hierarchy, symbol table, and definitions of methods. Then the methods are, currently manually, assigned to either hardware or software partitions (the “Partitioning” box in Fig. 1) and then the method definitions are transformed to suit their assigned partition (boxes labeled “Transformations”). Moreover, the partitioning box generates some macros (shown as “Instr-set extensions” box) that are required for proper compilation of the software 2
The OO-ASIP does have other features than simple hardware acceleration. Interested reader is referred to [4, 15] for more details.
The ODYSSEY Tool-Set for System-Level Synthesis of Object-Oriented Models
397
Fig. 1. The ODYSSEY Single-processor synthesis flow
partition; these macros represent hardware methods wherever they are called in the software partition. Transformed methods in each partition are then passed to their corresponding structure generator box that appropriately assembles them together. The resulting hardware (in SystemC) and software (in C++) can be simulated together, as the co-simulation of the post-synthesis system, in any environment that supports the SystemC class library.
4
System-Level Synthesis
The big picture of system-level synthesis and the correspondence between model and implementation elements are depicted in Fig. 2. The input consists of a set of classes along with a main() function (the left hand side of Fig. 2). The output is a synthesizable processor architecture comprised of some hardware units and a traditional processor core, along with a software architecture containing a set of software routines and a single thread main() function (the right hand side of Fig. 2). The implementations of hardware methods are put in the hardware modules in the middle of the OO-ASIP box in Fig. 2, whereas the implementations of software methods are put in the “traditional processor” module. The input main() function is converted to the thread main() routine in the processor software. The objects’ data are put in an object-identifier-addressable memory unit, referred to as object management unit or OMU. 4.1
Structure of the Tool
The synthesis tool is object-oriented itself. It consists of three major types of objects: an input parser object, an output writer object, and per partition synthesizer objects re-
398
M. Goudarzi and S. Hessabi
Fig. 2. The big picture of transformations in the system-synthesis process
siding between the previous two. The big picture of these objects and their functionality are briefly presented below. For ease of referencing, the following definitions are made: Definition 1: The input OO model consists of a class library that declares and defines all available classes. We refer to this class-library-under-synthesis as CLUS hereafter. Definition 2: The declaration of objects and the sequence of method calls among them is defined in a main() function in the input OO model. This application-under-synthesis is referred to as AUS hereafter. Input Parser: This object reads in the input file and produces a parse tree along with other necessary data structures for further processing. If the input model contains several files, they are all concatenated into a single one for easier parsing. The input file contains both the CLUS and the AUS. At the construction time of this object, the input file is parsed, the hierarchy of classes is built, the symbol table is generated, and the member functions and their definitions are found. Then, the system is partitioned by assigning each method to the hardware or the software partition. Synthesizers: These are the main objects responsible for synthesizing hardware and software methods. They operate on individual method definitions and transform them to suit hardware or software implementation according to their assigned partition. More details of these transformations are presented in Section 4.2. Output Writer: This object assembles all hardware and software methods synthesized by above Synthesizer objects and writes out the complete co-simulation model of the OO-ASIP (see Section 4.3). 4.2
Model Transformations
Since SystemC is actually a C++ class library itself, support for several C++ constructs is provided effortlessly. However, some constructs need special handling and transformations, explained below, due to the special architecture of the OO-ASIP. This speciality arises from the partitioning quantum of our methodology; we assign each class method to either partition, and consequently, dispatching a call to method implementa-
The ODYSSEY Tool-Set for System-Level Synthesis of Object-Oriented Models
399
tions, passing parameters to them, and returning values from them needs to be carefully worked out so that all four cases of hardware or software caller to hardware or software callee are appropriately handled. Furthermore, the methodology allows redefinitions of the same virtual method to reside in different partitions. This is a significant feature of the methodology that enables systematic application of software patches to extend, upgrade, or correct missing or faulty hardware units. To provide efficient dispatching of a virtual method call to hardware- as well as software-method implementations, we have devised a network-based dispatching mechanism presented in [15]; we view each method call as a packet to be sent over a network from the caller to the callee, carrying the call parameters as its data payload. This approach necessitates a special object numbering scheme, instead of the traditional address-in-memory scheme, that in turn necessitates special treatment of object instantiation and pointer-to-object declaration and use. The following paragraphs discuss each of the above special handlings and presents the corresponding transformations applied to the source C++ routines. Object Instantiation. In a traditional processor, each object is assigned a memory portion whose starting address identifies the object. In the same way, we also allocate memory portions for object data; however, our special object-numbering scheme requires each object to be identified by a new object-identifier comprised of the identifier of the class of the object (i.e. cid) and the unique-in-this-class number assigned to this object (i.e. objn). We refer to this (cid, objn) pair as oid hereafter. This change in the object identifier introduces two issues: allocating a unique oid per object, and mapping it to the memory address when the object data is to be accessed. The first issue is handled by keeping track of per-class objn numbers already assigned to objects. The second issue is handled by a mapping hardware (the OMU) that translates the oid to its physical address. In other words, the OMU is an oid-addressable memory. Object-Pointer Declaration and Use. The change we have proposed in the object identifier results in a change in the values that the pointers hold; a pointer holds oid values now. In transforming a class method (regardless of its being hardware- or softwaremethod), wherever the address of an object is assigned to a pointer, the oid of that object is replaced instead. Access to Object Attributes. To access the attributes of an object, the physical address of the object data in memory must be known. This was readily available in traditional processors as the object identifier, but in our methodology this needs to be extracted from the oid. To do this, our synthesis tool identifies all object access statements in the input program and replaces them with an OBJ ATTR( oid, attr index ) macro in the output. The first operand of the macro is the oid of the desired object, which is translated by the macro to the starting address of the object, and the second operand is the index of the desired attribute in the object data storage. Virtual Method Calls. To invoke the packet-based method-dispatching mechanism in hardware- and software-methods, the virtual method calls in the input program are replaced by special macros of VMC BY HW and VMC BY SW respectively. Both
400
M. Goudarzi and S. Hessabi
macros take two parameters; the first parameter is the oid of the called object and the second one is the identifier of the called method. Passing Parameters to Virtual Methods. The same packet that dispatches a method call can indeed carry the parameters of the call. Simple data types, e.g. int, char, float, are trivial in this regard; however, more interesting cases arise when considering complex data types such as objects, arrays, pointers, and references. Objects and arrays can be passed by value, but this incurs an overhead due to transfer of possibly large amounts of data between the caller and the callee. Call by reference, and also pointer parameters, are only supported for objects since only objects are stored in the global data memory that is equally accessible to all hardware and software method implementations; if pointer parameters and/or call-by-reference are desired for other data types, the actual parameters can be declared as objects instead. Returning Values from Virtual Methods. As in C++ programs, method calls are blocking in the system implementation; i.e. the caller waits for the callee to finish its operation. This end-of-operation is announced by a METHOD DONE packet from the callee to the caller. This same packet can also carry the return value. All return and return(val) statements in method definitions are respectively replaced by RETURN and RETURN VAL(val) macros that accomplish the necessary packet assembly and posting. 4.3
The Co-simulation Model
Our tool-set not only generates the hardware and software partitions, but also produces a simulatable post-synthesis model to allow integration-test before completion of downstream synthesis steps. This co-simulation model is in SystemC and contains hardwareas well as software-methods in their transformed C++ form; consequently, it not only provides integration-test earlier in the synthesis process, but also runs much faster than detailed post-downstream-synthesis co-simulation. This enables the designer to verify the system-synthesis process in isolation from the downstream process. The architecture of the co-simulation model is shown in Fig. 3. The OO-ASIP module has two network lines, net in and net out, to connect to other OO-ASIPs on a network. The reset input is used to restart the OO-ASIP. The clk input is required by the SystemC synthesis tool (it only supports SC CTHREAD, i.e. clocked thread, processes for synthesis) and could be omitted if only co-simulation were desired. Assertion of the reset signal starts the co-simulation. This triggers restarter() process which invokes the thread main() routine. This routine first calls constructors of the objects, and then continues as in the original main(). To make a method call, the thread main() routine assembles a packet, sends it to the net out output of the cpu module, and waits for the method completion. In our current implementation, net in and net out ports of the OO-ASIP module are externally connected together while all hardware modules and the cpu itself are listening to the network and get invoked by any new packet sent there. Everybody checks the packet destination against its own address and takes it if they match. Each hardware module implements only one hardware method, whereas the cpu can contain several software methods. Thus, if the recipient is a hardware module, its single transformed-by-the-tool method code is run; but if the
The ODYSSEY Tool-Set for System-Level Synthesis of Object-Oriented Models
401
Fig. 3. The architecture of the post-synthesis co-simulation model
cpu receives the packet, it is internally dispatched to the appropriate software routine implementing the called method. Every hardware or software method may also call a virtual method; the procedure of method dispatching is the same as non-virtual calls. All software and hardware methods may also access attributes of an object; this is redirected to the OMU which implements an object-identifier-addressable memory.
5
Experiments
We implemented our system-synthesizer tools in C++; the implementation, in its current state, consists of about 3000 lines of code. It has taken about two man-months to devise the co-simulation model and manually develop and test it and an additional 5 manmonths to develop and test the tools.
Table 1. Summary of the test cases devised for the tools Test test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 tests 11-18
Description Object instantiation + constructor invocation. Pointer declaration, assignment, and use. Virtual method call (VMC) by the main() function. The call is dispatched to a hardware-method, it finishes, and then control is passed back to main(). The same as above, but to a software-method callee. VMC by the main() to a hardware method. This time both the hardware method and main() access and manipulate the object attributes. The same as above, but to a software-method callee. VMC by the main() while passing two parameters: a by-value parameter, and a by-reference object. The same as above, but to a software-method callee. VMC by the main() to a hardware-method that returns a value The same as above, but to a software-method callee. The same as test3 to test10 above, but this time a hardware method starts the transactions.
402
M. Goudarzi and S. Hessabi
To thoroughly verify proper operation of the tool, we devised a comprehensive set of test cases that incrementally covered all aspects that the tool should handle (Section 4.2). Table 1 gives a summary of these test cases and the points that each adds to previous ones. The first two test cases deal with object instantiation and object-pointer declaration and use. Tests number 3 to 10 verify proper synthesis when a software caller makes a virtual method call (tests 3 and 4), when attributes of the object are manipulated by the caller and the callee (tests 5 and 6), when by-value and by-reference parameters are passed to the callee (tests 7 and 8), and finally when a value is returned by the callee (tests 9 and 10). This same set of tests are performed for a hardware caller by tests number 11 to 18. The co-simulation capability of our generated hardware-software system enabled us to make sure that the system-synthesis is correctly performed on each test case by running the pre- and post-synthesis programs and comparing their outputs against each other. This same capability can benefit system-designers in verifying the systemsynthesis process and validating the partitioned system before proceeding to downstream synthesis steps.
6
Summary and Conclusion
The main thrust of this paper is to describe and discuss implementation details and advantages of an EDA tool-set that automates design of embedded systems in the ODYSSEY methodology. These tools automatically generate hardware, software, and their interface from a given class library and application. Although the methodology is language-neutral, its implementation (i.e., the EDA tool-set) cannot stay neutral on this. We chose C++ as the input language and SystemC-C++ as the output for hardware and software components respectively; these choices eliminated error-prone language transformations. Furthermore, this paper introduced a hardware-software co-simulation model that our EDA tool-set generates as the result of system-level synthesis. This co-simulation model is in SystemC, and hence, is an executable model of the hardwaresoftware partitioned system generated by the tools. This property was used in this paper to efficiently verify correct operation of our design automation tools by comparing the results of executing pre- and post-synthesis models. This same approach can be used to validate consistency of generated hardware and software partitions and their interface. This efficient validation, due to executable high-level co-simulation model, allows early detection of probable mistakes or inconsistencies and serves as a design checkpoint before diving into time-consuming and intricate process of elaborating hardware and software partitions. We are currently working on downstream synthesis steps (see Fig. 1) to complete the automated tool-chain from concept to working implementation on an FPGA board so as to make it practically possible to realize embedded systems in ODYSSEY style. Real-life case studies will be conducted afterwards to evaluate, tune, and/or amend the tool chain and/or the methodology.
The ODYSSEY Tool-Set for System-Level Synthesis of Object-Oriented Models
403
References 1. Flaherty, N.: On a higher level. The IEE Review (2004) 22–24 Report from the 41st Design Automation Conference. 2. Schubert, T., Hanisch, J., Gerlach, J., Appell, J., Nebel, W.: Evaluating a system-based design flow. IEE Electronics Systems and Software (2004) 29–33 3. ODYSSEY Project: Online Homepage. (2005) http://ce.sharif.ir/˜ odyssey. 4. Goudarzi, M., Hessabi, S., Mycroft, A.: Object-oriented ASIP design and synthesis. Proc. of Forum on specification & Design Languages (FDL) (2003) Frankfurt. 5. Goudarzi, M., Hessabi, S., Mycroft, A.: Object-oriented embedded system development based on synthesis and reuse of OO-ASIPs. Journal of Universal Computer Science (J.UCS) (2004) In press. 6. Ashenden, P., Wilsey, P., Martin, D.: SUAVE: Painless extension for an object-oriented VHDL. Proc. of VHDL Int’l Users’ Forum (VIUF) (1997) 7. Radetzki, M.: Synthesis of Digital Circuits from Object-Oriented Specifications. PhD thesis, University of Oldenburg, Germany (2000) 8. Schumacher, G., Nebel, W.: Inheritance concept for signals in object-oriented extensions to VHDL. Proc. of EURO-DAC with EURO-VHDL (1995) 9. Radetzki, M., Putzke-Roming, W., Nebel, W., Maginot, S., Berge, J., Tagant, A.: VHDL language extensions to support abstraction and re-use. Proc. of Workshop on Libraries, Component Modelling, and Quality Assurance (1997) 10. OASE Project: Objektorientierter hArdware/Software Entwurf: Online Home Page. (2004) http://www-ti.informatik.uni-tuebingen.de/˜ oase/. 11. Kuhn, T., Oppold, T., Winterholer, M., Rosenstiel, W., Edwards, M., Kashai, Y.: A framework for object oriented hardware specification, verification, and synthesis. Proc. of Design Automation Conference (DAC) (2001) Las Vegas, Nevada. 12. Young, J., MacDonald, J., Shilman, M., Tabbara, A., Hilfinger, P., Newton, A.: Design and specification of embedded systems in Java using successive, formal refinement. Proc. of Design Automation Conference (DAC) (1998) 13. International Semiconductor Roadmap Committee: International Technology Roadmap for Semiconductors (ITRS)-Design. (2003) http://public.itrs.net. 14. Keutzer, K., Malik, S., Newton, A.: From ASIC to ASIP: the next design discontinuity. Proc. of Int’l Conference on Computer Design (ICCD) (2002) 15. Goudarzi, M., Hessabi, S., Mycroft, A.: Overhead-free polymorphism in network-on-chip implementation of object-oriented models. Proc. of Design Automation and Test in Europe (DATE) (2004) Paris.