SystemC Based Object Oriented System Design - Semantic Scholar

2 downloads 24775 Views 116KB Size Report
schedules become tighter, the electronic design automation (EDA) ... following the discussions in the SystemC mailing list has revealed that the current version ...
SystemC Based Object Oriented System Design Seppo Virtanen Dragos Truscan Johan Lilius [email protected] [email protected] [email protected] Turku Centre for Computer Science (TUCS) Lemmink¨aisenkatu 14 A, FIN-20520 Turku, Finland 1

Introduction As the complexity of electronic systems constantly increases and at the same time design schedules become tighter, the electronic design automation (EDA) community has shown a high interest for new design methods and tools. One interesting development is the adopting of executable specifications as a potential replacement for the traditional written specifications. Executable specifications are expected to provide unambiguity, completeness and correctness to system specification [4]. For designers to be able to create an executable specification, a suitable description/programming language or environment is needed. Recently C and C++ [10] have been proposed as bases for languages and environments for creating executable specifications [3, 4, 7]. The choice to use these languages as the basis for an executable specification design environment is the most trivial of solutions in terms of availability and cost: existing tools can be used, since companies already use C++ in their software development and C in their embedded system programming, and operating systems like Linux provide C and C++ compilers and utilities free of charge. However, these languages are designed for writing computer programs, not for describing computers or other hardware devices. Therefore they lack necessary functionality and features for describing clocks, signals, reactivity and parallel processing. Also, design flows that start from a C or C++ based functional level description contain a “jump” in which the functional model is translated into a HDL [2, 5]. This phase is often manual and involves refining the model down to the RTL level. To solve this problem, either a system description language should be built on top of C or C++, or a language designed specifically for system description should be created. SystemC explores the first option. It is a recently introduced C++ class library for designing executable specifications and cycle-accurate simulators of hardware in C++. It provides support for hardware-oriented data types like modules, ports and signals. Originally there were two major goals in designing SystemC [5]: to provide a single language framework for coverifying systems at varying, possibly mixed, abstraction levels, and to allow system designers to gradually refine their models towards the RTL level without translating them into a HDL. When SystemC was introduced in 1999 we decided to experiment with it in our protocol processor development effort, since we saw a lot of potential in it and were quite enthusiastic about it. SystemC development seemed to be on the right track - we expected to be able to combine the advantages of object oriented (OO) programming and cycle accurate simulations accompanied with suitable data types for describing signals and ports efficiently. However, following the discussions in the SystemC mailing list has revealed that the current version of SystemC (1.0.1) is widely used for constructing low level descriptions of hardware devices in a similar way as hardware is described in traditional HDL’s. Moreover, to our surprise SystemC (as presently defined) seems to actively discourage the use of object oriented programming techniques.

Fourth International Forum on Design Languages (FDL’01), Lyon, France, September 2001

sc_object SocketManager

FuBase

NetControl

FunctionalUnit

Bus

sc_object_manager sc_module

TriggerSocket

SystemC

Socket

OutSocket InSocket

Matcher

Compare

Counter

CRC

RandomGen

GenReg

...

TACO Library

Figure 1: TACO class hierarchy and connection to SystemC. 2

The TACO Library We are currently developing a methodology for obtaining an optimized protocol processor architecture, its instruction set and application code from a high abstraction level protocol processing application description (the TACO project, [11]). We have modified and simplified the TTA (Transport Triggered Architecture) [1] microprocessor architecture for use in our protocol processors. A TTA processor is formed of FU’s (functional units) that are connected to an interconnection network of data buses with sockets. An interconnection network controller unit controls data transfers between FU’s. TTA is extensible, allowing it to be customized to different protocols, and it is optimized for data transfer, which is the main function of a telecommunication protocol. To rapidly evaluate different processor architectures designed for executing the same algorithm (i.e. design space exploration) we have constructed an object oriented protocol processor simulation framework. It is implemented as a library of components written in SystemC. The component library contains implementations of functional units, sockets, interconnection buses, and the program dispatch logic. Using this library it is possible to construct cycle accurate simulators of TACO processors. We have also implemented corresponding synthesizable VHDL models for all the components in our library. The level of abstraction used in TACO simulator implementations is heterogenous in the following sense: the inter-module communication is handled at the RTL level, whereas the internal functionality of the modules is implemented as higher level C++ using SystemC’s fixed bitstring length data types (e.g. sc uint, 32-bit unsigned integer). The motivation for our use of heterogenous abstraction in our simulator implementations is that since we know the execution time (in cycles) for each module in the processor (based on VHDL model synthesis), we can use high-level C++ inside the modules as long as we insert the correct amount of cycle delays into each module. Since the functional units in a TACO processor (or more generally, in a TTA processor) have a very similar interface, we utilize inheritance in our simulator (see figure 1). This is done by gathering the behavior that is the same for every functional unit into a parent class, and placing only the additions to this port/signal configuration required by individual modules to the child classes. The approach has obvious benefits: the code is more compact and readable (the interface code is not repeated multiple times), there are less errors to debug (only additions to the interface are coded) and adding new functional units to the SystemC component library is faster (most FU’s in our protocol processors differ only in the internal implementation, not the physical interface). The execution of a TACO simulator consists of two phases. In the setup phase all modules are instantiated. This phase relies heavily on polymorphism to allow automatic socket instantiation and addressing, and to connect different kinds of functional units to buses through

typedef module SC CURRENT USER MODULE; | class FuBase: public sc module {...}; module(sc module name); | template class FunctionalUnit: | public FuBase{ | typedef CB SC CURRENT USER MODULE; ...}; | class Matcher: public FunctionalUnit | {...};

Figure 2: Code examples. On the left, the expansion of SC CTOR(module). On the right, the declarations required for using SystemC port types in child classes. sockets. After this all the modules in the processor have been instantiated. No more modifications to the architecture are made, and polymorphism is no longer used. The second phase, simulation, is started when the command sc start() is issued in sc main. It is important to realize that at the moment the simulation starts, the processor architecture is completely static and no more modules are dynamically constructed. For this reason, it is possible (although it would require some effort) to mechanically remove the polymorphic code used for automatic simulator construction. Also the inheritance can be mechanically removed, thus making it possible to have static module instantiation and stand-alone modules without a class hierarchy. However, in the TACO framework this is not necessary, since we are investigating methods for producing a top level VHDL file (mapped to our synthesized VHDL components) from sc main() functions of TACO simulators. 3

Limitations of SystemC There are a number of issues about the design of SystemC that we would like to point out. Some are more concerned with what could be called “good C++ practice” while others are more about the architecture and API of SystemC. There are two rules that are taught in most elementary C++ programming courses: don’t use macros (section 7.8 of [10]), and separate interface from implementation (item 34 in [6]). In SystemC many constructs are implemented as macros that rearrange text in the program code before the compiler sees it. This causes many difficulties in debugging the code (e.g. debuggers like DDD show macros disassembled). For this reason an instruction (macro) that causes an error or malfunction in the program is often difficult to find. Macros have importance in writing C code, but the use of macros in C++ is discouraged in literature. A more general problem with the SystemC macro approach is that it breaks the distinction between interface definition files (header files, *.h) containing only declarations and implementation files (code files, *.cpp), containing the bodies of the methods. Although this distinction is not enforced by the C++ language, it is considered good software engineering practice for several reasons. First, readability of the code is increased because interface definitions are not intermingled with implementation details. Secondly, recompilation speed is increased, because changing an implementation only causes the implementation file to be recompiled. In our current implementation a change may cause all files to be recompiled. Interestingly, the SystemC documentation recommends giving the module constructor implementation within the interface definition file. As we wanted our simulator to be easily expandable, we early on decided to use inheritance as a structuring mechanism. However, soon we noticed that this kind of implementation technique seems to be actively discouraged in SystemC version 1.0.1. After much debugging we were finally able to isolate the cause of the problem into the constructors of our functional unit classes. The constructor for an object of class module is declared as SC CTOR(module) in SystemC. This is expanded to the declaration given on the left side of figure 2. The first line defines a type name alias, that we will return to below. The second line is interesting. It declares a constructor for objects of class module that takes an anonymous sc module name

object as a parameter. The life-time of the object is the scope of the constructor and it is used to push the current module onto the simulation context stack. This makes sure that all ports declared in the class are attached to the correct instance of class module in the simulator. So when building the inheritance hierarchy with sc module as the base class, we must make sure that all the parent classes are instantiated within the scope of the correct sc module name object. This can be achieved by adhering to the following convention: Each non-leaf class must have a default constructor (a constructor with empty argument list). However a second problem still remains. This has to do with the first line with the typedef, which declares the type SC CURRENT MODULE to be an alias for the name of the current module. This type is needed in macros that are used to connect the execution of a method to the correct simulation context. However since non-leaf classes are created with the default constructor the constructor will not define SC CURRENT MODULE and thus the program will fail to compile. We have resorted to C++ templates to overcome this particular problem. We thus implemented a multi-level class hierarchy, with the concrete functional unit implementation classes as leaf-classes and two intermediate levels before the SystemC level (the sc module class). The class declarations for the three-level class hierarchy are shown on the right side of figure 2. The top-level class (FuBase in figure 1) is an abstract class1 that defines the interface to the functional unit classes. The second-level class FunctionalUnit is a template class that contains the common functionality of the functional units. It is also used to set SC CURRENT MODULE to the correct type. Conceptually the template class FunctionalUnit together with the class FuBase forms the interface that all functional units support. 4

Conclusions SystemC clearly tries to prevent the use of inheritance. This prompted us to look a bit closer at research on the application of object-oriented techniques to hardware design. A survey of the literature reveals that the hardware design community has not reached a consensus on the usefulness of object-oriented techniques in hardware design [9]. The most interesting effort in this context is the attempt to add objects and inheritance to VHDL [8]. This project has revealed several difficult object-oriented concepts that don’t have a good mapping to hardware. These include inheritance, method call and protocols. The research thus seems to suggest that object-orientation does not fit hardware design very well. We believe that this is a misunderstanding. Object-orientation is more than an implementation language. It is a conceptual way of thinking and structuring the problem domain. In an object oriented design method objects can be viewed at three levels: 1. Conceptual level : The classes represent concepts in the domain of study. This view is taken very early in the analysis phase. 2. Specification level : The classes specify interfaces of the system. A type is the interface of the class. A type can have many classes that implement it, and a class can implement many types. 3. Implementation level : The classes represent code in a programming language. Both OO-VHDL and SystemC view objects as implementation level entities that should be directly mappable to hardware. If one takes this view it is clear that especially inheritance is non-trivial to map into hardware. Inheritance is an implementation technique that is used to implement subtyping in many object-oriented languages. Subtyping on the other hand allows polymorphism, where a function may be called with several different argument types. The reason that polymorphism is difficult to implement in hardware is simply that in hardware all types (objects) have to be static, since they are physical objects. However, we would like to claim that in any practical hardware design these kinds of situations do not arise, or the corresponding code can be rewritten in a way that circumvents the problem. This is so, because in an instance of a hardware system the set of objects is fixed. It does not change and thus 1

A class that cannot be instantiated.

the types of the variables in the program do not change while the system is running. Indeed this is exactly the case in the TACO library. Polymorphism and inheritance are very powerful concepts that have allowed programmers to increase their productivity substantially mainly because they enable reuse of code. Therefore, since hardware design is more and more becoming a programming activity, we believe that it is important to allow also hardware ”programmers” to use these techniques. We believe that the problems reported in section 3 can be attributed to the attempt to design an API that conforms to the view of objects as implementation level entities only. By reading the SystemC source-code we can see that by using the internal calls we could have probably obtained a cleaner design of the TACO library. Using the internals we could also have adhered to ”good C++ practice”. However since the internals are not really documented and standardized we decided to try our luck with the official API. Acknowledgements Financial support for this work from the Nokia foundation and the HPY research foundation is gratefully acknowledged by the first author. References [1] H. Corporaal. Microprocessor Architectures - from VLIW to TTA. John Wiley and Sons Ltd., Chichester, West Sussex, England, 1998. [2] D. D. Gajski, F. Vahid, S. Narayan, and J. Gong. Specification and Design of Embedded Systems. Prentice-Hall Inc., Englewood Cliffs, NJ, USA, 1994. [3] D. D. Gajski, J. Zhu, R. D¨omer, A. Gerstlauer, and Z. Shuqing. SpecC: Specification Language and Methodology. Kluwer Academic Publishers, Norwell, MA, USA, 2000. [4] J. Gerlach and W. Rosenstiel. System level design using the SystemC modeling platform. In Proceedings of the 3rd Workshop on System Design Automation, 2000. [5] S. Y. Liao. Towards a new standard for system-level design. In Proceedings of the Eighth International Workshop on Hardware/Software Codesign, 2000. [6] S. Meyers. Effective C++: 50 Specific Ways to Improve Your Programs and Designs. Addison Wesley Longman, Inc., Reading, MA, USA, 2nd edition, 1997. [7] M. Radetzki and W. Nebel. Synthesizing hardware from object-oriented descriptions. In Proceedings of the 2nd Forum on Design Languages, 1999. [8] G. Schumacher and W. Nebel. Inheritance concept for signals in object-oriented extensions to VHDL. In Proceedings of EURO-DAC’95 with EURO-VHDL’95, 1995. [9] G. Schumacher and W. Nebel. Object-oriented hardware modelling – where to apply and what are the objects? In Proceedings of EURO-DAC’96 with EURO-VHDL’96, 1996. [10] B. Stroustrup. The C++ Programming Language. Addison-Wesley Publishing Company, Reading, MA, USA, 3rd edition, 1997. [11] S. Virtanen and J. Lilius. The TACO protocol processor simulation environment. In Proceedings of the 9th International Symposium on Hardware/Software Codesign, 2001.

Suggest Documents