Embedded Systems Simulator By James McGill The School of Information Technology and Electrical Engineering The University of Queensland Submitted for the degree of Bachelor of Engineering (Honours) in the division of Computer Systems Engineering 5th February 2016 James McGill - 40793625 Embedded Systems Simulator ii James McGill - 40793625 Embedded Systems Simulator 5th June 2009 Head of School, School of Information Technology and Electrical Engineering, The University of Queensland, St. Lucia QLD 4072 Professor Paul Bailes, In accordance with the requirements of the Degree of Bachelor of Engineering (Honours) in the School of Information Technology and Electrical Engineering, I submit the following thesis entitled “Embedded Systems Simulator” This thesis was performed under the supervision of Dr. Peter Sutton. I declare that the work submitted in this thesis is my own, except as acknowledged in the text and footnotes, and has not been previously submitted for a degree at The University of Queensland or any other institution. Yours sincerely, James McGill iii James McGill - 40793625 Embedded Systems Simulator iv James McGill - 40793625 Embedded Systems Simulator Dedicated to my friends and family v James McGill - 40793625 Embedded Systems Simulator Acknowledgements I would like to acknowledge the guidance and support of Dr. Peter Sutton throughout this thesis, and also thank him for initiating this project. I would also like to thank those who made the evaluation of this thesis possible by allowing me to collect and use their embedded systems projects. vi James McGill - 40793625 Embedded Systems Simulator Abstract Embedded systems are designed to perform specific computing tasks, and therefore often lack the resources required to allow iterative software development and debugging without specialized hardware. To overcome these issues, PC based simulators can be used to allow the behaviour of a digital system to be evaluated and to utilise the debugging capabilities of a PC. This thesis presents the implementation of a cross-platform C++ framework and application for performing simulations of digital embedded systems composed of multiple components. Components are loaded from dynamic libraries, allowing extensions to the system to be developed independently, and simulated using a discrete event algorithm. The simulators flexibility has been utilized to develop several components, including an implementation of the AT90S8515 8-bit AVR microcontroller. The simulator has been demonstrated to correctly perform perceptually real-time hardware/software co-simulation of a benchmark system composed of an AT90S8515 microcontroller, clocked at 4 MHz, and several other components, while maintaining an accurate graphical representation of the system state. Automated testing has been used to verify the basic functionality of the full AT90S8515 instruction set, as well as the microcontroller’s Timer/Counters, interrupt and USART peripherals, while structured system testing has been used to verify that the project meets and exceeds all requirements originally proposed. vii James McGill - 40793625 Embedded Systems Simulator Table of Contents Acknowledgements ................................................................................................................... vi Abstract .................................................................................................................................... vii Table of Contents .................................................................................................................... viii List of Figures .......................................................................................................................... xii 1.0 Introduction and motivation ................................................................................................. 2 1.1 Scope ................................................................................................................................ 2 1.2 Outcomes .......................................................................................................................... 3 1.3 Report Outline .................................................................................................................. 4 2.0 Literature review and background information .................................................................... 6 2.1 Discrete event and embedded systems simulation ........................................................... 6 2.2 Event set data structures ................................................................................................... 7 2.3 Development tools............................................................................................................ 8 2.4 Testing methodologies ................................................................................................... 10 2.5 Past theses ...................................................................................................................... 11 3.0 Prior art ............................................................................................................................... 12 3.1 AVR Simulator IDE ....................................................................................................... 12 3.2 Proteus VSM .................................................................................................................. 13 3.3 Atmel AVR Studio ......................................................................................................... 15 3.4 miSim DE ....................................................................................................................... 16 4.0 Goals and project requirements .......................................................................................... 18 4.1 Software architecture requirements ................................................................................ 18 4.2 Required components ..................................................................................................... 19 4.3 Required documentation ................................................................................................ 20 4.4 Performance and portability requirements ..................................................................... 20 4.5 Additional work.............................................................................................................. 21 4.6 Elements considered to be outside scope ....................................................................... 21 viii James McGill - 40793625 Embedded Systems Simulator 5.0 Implementation of the simulation framework .................................................................... 22 5.1 Architectural overview ................................................................................................... 22 5.2 Components .................................................................................................................... 23 5.2.1 Providing a graphical representation of a components state ................................... 24 5.3 Events ............................................................................................................................. 24 5.4 Pins ................................................................................................................................. 25 5.5 Discrete event simulation ............................................................................................... 27 5.5.1 Enqueuing events .................................................................................................... 28 5.5.2 Simulator timestamp ............................................................................................... 28 5.5.3 Memory management .............................................................................................. 29 5.6 Real-time execution........................................................................................................ 29 5.7 Error reporting ................................................................................................................ 29 5.8 Graphical user interface ................................................................................................. 30 5.9 Cross platform plug-in architecture................................................................................ 31 5.10 Automatic plug-in documentation generation .............................................................. 33 5.11 Persistence of simulation properties using simulation projects.................................... 33 5.11.1 Loading simulation projects .................................................................................. 34 6.0 Implementation of plug-in components ............................................................................. 36 6.1 Atmel AT90S8515 8-bit microcontroller ....................................................................... 36 6.1.1 Common AVR functionality ................................................................................... 36 6.1.2 Instructions .............................................................................................................. 37 6.1.3 Registers and data storage ....................................................................................... 38 6.1.4 Automatic generation of skeleton classes ............................................................... 39 6.1.5 Interrupts ................................................................................................................. 40 6.1.6 Cycle correct execution ........................................................................................... 41 6.1.7 Status register .......................................................................................................... 41 6.1.8 Graphical user interface and debugging functionality ............................................ 42 ix James McGill - 40793625 Embedded Systems Simulator 6.1.9 Internal AVR peripherals ........................................................................................ 43 6.1.10 EEPROM Peripheral ............................................................................................. 44 6.1.11 AT90S8515 Implementation ................................................................................. 44 6.2 TCP/IP based RS-232 Transceiver ................................................................................. 45 6.3 Speaker ........................................................................................................................... 46 6.4 Additional components .................................................................................................. 47 7.0 Verification of solution ...................................................................................................... 50 7.1 Testing methodologies ................................................................................................... 50 7.1.1 Testing of the complete system ............................................................................... 50 7.1.2 System benchmark .................................................................................................. 52 7.1.3 Automated testing of the Atmel AT90S8515 plug-in ............................................. 54 7.2 Results ............................................................................................................................ 56 7.2.1 Manual testing of components and simulator framework ....................................... 56 7.2.2 Performance ............................................................................................................ 56 7.2.3 Stability ................................................................................................................... 58 7.2.4 AT90S8515 ............................................................................................................. 58 7.3 Functionality and deliverables ....................................................................................... 59 7.3.1 Required components .............................................................................................. 60 7.3.2 Maintainability ........................................................................................................ 60 7.3.3 Documentation ........................................................................................................ 60 7.3.4 Portability ................................................................................................................ 61 7.4 Discussion ...................................................................................................................... 62 7.5 Reflection of project management ................................................................................. 65 8.0 Future work ........................................................................................................................ 68 8.1 Project editor .................................................................................................................. 68 8.2 Improved debugging capabilities ................................................................................... 68 8.3 Automated testing framework ........................................................................................ 68 x James McGill - 40793625 Embedded Systems Simulator 8.4 Development of additional components ......................................................................... 69 8.5 Improved separation of simulator state from graphical state ......................................... 69 9.0 Conclusion .......................................................................................................................... 70 Appendix A : XML Schema for simulation project files ......................................................... 77 Appendix B : Django templates for AvrInstruction and AvrMemory skeleton classes ........... 79 Appendix C : Manual testing plan............................................................................................ 90 Appendix D : Summary of manual tests .................................................................................. 91 Appendix E : Automated testing command language .............................................................. 95 Appendix F : Python script to save simulator state from AVR Studio .................................... 96 Appendix G : Project progress plan ......................................................................................... 98 xi James McGill - 40793625 Embedded Systems Simulator List of Figures Figure 1: CSSE1000 project board............................................................................................. 9 Figure 2: AVR Simulator IDE with EEPROM and LCD peripherals enabled. ....................... 13 Figure 3: Real time simulation of a graphical LCD in Proteus VSM ...................................... 14 Figure 4: Expanded register view from AVR Studio. .............................................................. 16 Figure 5: Overview of simulator architecture .......................................................................... 23 Figure 6: Cyclic notification problem. ..................................................................................... 26 Figure 7: Transitive pin connections. ....................................................................................... 26 Figure 8: Simulator graphical user interface. ........................................................................... 31 Figure 9: Documentation automatically produced for the switch component. ........................ 33 Figure 10: AT90S8515 class architecture ................................................................................ 37 Figure 11: Demonstration of operands within an opcode (MOV opcode) ............................... 38 Figure 12: AVR address segments for an AT90S8515. ........................................................... 39 Figure 13: Conditions required for an interrupt to be triggered. .............................................. 41 Figure 14: The AVRCore debugging window. ........................................................................ 43 Figure 15: Detection of incorrect baud rates during simulation............................................... 46 Figure 16: Formula for conversion between frequency (Hz) and MIDI Note ID .................... 47 Figure 17: Simulation of an 80 character LCD, driven by an AT90S8515 microcontroller. ... 48 Figure 18: Simulator error, as identified by the automated project testing framework. .......... 51 Figure 19: Hardware used by the Tetris benchmark. ............................................................... 53 Figure 20: Simulation of the Tetris benchmark. ...................................................................... 53 Figure 21: Output from the AVR Testing Framework. ............................................................ 55 Figure 22: Error between simulation time and wall clock time over 150mS. .......................... 57 Figure 23: Error between simulation time and wall clock time over 9 seconds ...................... 58 Figure 24: Frequency distribution of total instruction coverage (calls) over all automatic tests. .................................................................................................................................................. 59 Figure 25: Simulator running on Ubuntu Linux (a) and Mac OS X 10.5 (b)........................... 61 Figure 26: Comparison of simulator speed on multiple operating systems. ............................ 62 xii James McGill - 40793625 Embedded Systems Simulator List of Tables Table 1: Pin value protocol. ..................................................................................................... 25 xiii James McGill - 40793625 Embedded Systems Simulator 1 James McGill - 40793625 Embedded Systems Simulator 1.0 Introduction and motivation Embedded systems computing is a broad field, encompassing the development of all digital systems developed to perform specific computing tasks [1]. The narrow focus on functionality within embedded systems means that they often lack the resources required to allow iterative software development and debugging without expensive tools [2]. These systems also often require the design and manufacture of specialized hardware to be completed before software can be tested. To overcome these issues, PC based simulators can be used to allow the behaviour of the system to be evaluated prior to construction, and to utilise the debugging facilities of a PC, such as a monitor and keyboard. While many programs capable of simulating embedded digital logic already exist [3,4,5] they are often targeted at professionals and are difficult to use or prohibitively expensive. Additionally, few of these products are able to simulate a microcontroller executing code as part of a system consisting of multiple peripherals, such as switches or Liquid Crystal Displays (LCDs). The need for those new to the development of embedded systems to be able to easily develop and test systems without incurring an unreasonable level of expense led to the proposal by Dr. Peter Sutton and Mr James McGill to develop an extensible embedded systems simulator. 1.1 Scope The proposed software is intended to support fast and accurate simulation of systems composed of multiple simulated digital electronic components, while remaining flexible enough to allow additional components to easily be developed. The state of the simulation is 2 James McGill - 40793625 Embedded Systems Simulator intended to be displayed using a graphical interface, providing a simple method for developers to interact with the system under simulation. Accurate simulation of analogue components, or of the effects of capacitance, resistance and inductance on digital logic, is considered to be outside the scope of the project, as is the development of a schematic editor for the simulator. A more detailed examination of the goals of the project is presented in Chapter 4.0. 1.2 Outcomes A simulation framework has been developed which is able to perform fast and accurate simulations of systems composed of multiple components. The framework allows additional simulated components to be developed independently and dynamically loaded as required. The state of the system is represented using an extensible Graphical User Interface (GUI) which, combined with real-time simulation speeds, allows users to interact with the system in a way that is consistent with the use of the system’s physical counterpart. In order to demonstrate the usefulness of the framework, several simulated components, including an Atmel AT90S8515 microcontroller, have been developed. Structured testing has been used to demonstrate that these components function correctly. In addition, documentation in the form of tutorials and an instructional video has been developed to assist those seeking to use or extend the simulator. 3 James McGill - 40793625 Embedded Systems Simulator The framework and components developed compile and run on multiple operating systems, including Windows XP, Mac OS X and Linux. The full source code for the software developed is available on a CD-ROM which accompanies this document. 1.3 Report Outline The remainder of this document is used to discuss the theory behind, and implementation of, the embedded systems simulator. Chapters 2 and 3 provide a review of the academic literature relevant to the development of the simulator, as well as a review of the prior art in this field. Chapter 4 outlines the specific goals and requirements put in place before the development of the simulator, Chapters 5 and 6 present the methods used to implement the simulator framework and several component plug-ins, and Chapter 7 outlines the steps used to test the simulator and plug-in components, and evaluates the success of the project. Chapter 8 proposes a number of possible extensions to the work completed thus far, presenting possible future avenues for research in this area. A detailed summary of the project’s goals, implementation, and outcomes is included in Chapter 9. 4 James McGill - 40793625 Embedded Systems Simulator 5 James McGill - 40793625 Embedded Systems Simulator 2.0 Literature review and background information In order to ensure that the simulator is able to perform as efficiently as possible, this thesis has built upon the prior work and research of many people. An examination of this literature has served as a key component in the evaluation of alternative implementation methods. The most relevant literature and background information relating to this thesis is presented in the following sections. 2.1 Discrete event and embedded systems simulation Discrete event simulation, a simulation method in which the model for the system being simulated is updated only at discrete intervals of time [6], is one of the most common methods for simulating digital systems [7]. This technique lends itself particularly well to functional simulations of synchronous systems because of the discrete nature of clock driven events, but can also be used to approximately model continuous systems [6]. Simulation of digital systems can either achieve functional accuracy, in which the each simulated component behaves as a black box and only the inputs and outputs are simulated correctly, or can simulate the system at the gate level, in which the exact behaviour of each component, including the timing of internal events, is simulated accurately [8,9]. Although hardware can be used to achieve real time low level simulation and verification of digital systems, simulating the same level of detail in software incurs significant time penalties, making real time simulation impossible [10]. However, for simple systems, the timing information extracted from functional simulation may approximate that expected from low level simulations, allowing faster simulation with a similar level of accuracy [8]. When primarily investigating the results of hardware and software interacting in co-simulation, as is the goal of this thesis, describing each component at a functional level, rather than a gate 6 James McGill - 40793625 Embedded Systems Simulator level, is expected to give the greatest chance of the simulator being able to perform at realtime speeds [10]. In order to achieve faster simulation times, a number of techniques have been proposed which reduce unnecessary computations during the simulation of embedded systems. In their paper Muhr and Holler [11] identify that, even in functional simulation, simulation speed decreases significantly as the clock speed of the system under examination increases. In order to achieve near real-time simulations of digital systems with high clock speeds they propose a model by which the future state of part of the system can be interpolated for periods of time over which the inputs remain stable, and the effects of a change on the output remains constant [11]. Gauthier and Jerraya [10] suggest a similar method for improving performance through data suppression, in which the state of various subsystems in a microcontroller are not updated during the simulation if transitions to future simulator states can be shown to occur independently of this value. Simulation of an embedded system may also be performed using a stochastic model which defines the probability of transitioning to a specific state [12]. While suitable for modelling the expected performance of a system, this method cannot be used to develop a consistent and reliable model of a system’s behaviour. 2.2 Event set data structures An event set is an abstract data structure used in discrete event simulation to maintain a list of events to run, ordered by their scheduled time of execution [13]. The event set implementation plays a key role in determining the speed of the simulator, with event set manipulation expected to take up to 40% of the simulation processing time in most cases [14]. 7 James McGill - 40793625 Embedded Systems Simulator The simplest implementation of an event set is a linear linked list of events, which can enqueue an item in O(n) time and dequeue it in O(1) [14]. Owing to the simplicity of this algorithm, link lists demonstrate the best performance of all event set algorithms when the event set never grows beyond 20 items [14]. More complex algorithms, such as Calender Queues [15] and MLists [16], are able to make use of multiple data structures in order to address the need for faster simulation event set operations. Both are expected to achieve O(1) amortized execution times by taking advantage of the discrete nature of events in discrete event simulations, and therefore bucketing scheduled execution times. Unfortunately, the overhead required to perform this means that these implementations only perform well on large sets of events. 2.3 Development tools When attempting to undertake any software development project, it is first necessary to understand the capabilities and limitations of the available development tools. In order to ensure that the simulator can be used on multiple platforms, thought must be given to the choice of programming language and libraries. While writing the simulator instructions in an assembly language may allow it to achieve greater speed [17] it would do so at the expense of portability. Languages such as Java and C# overcome this problem by compiling to intermediate byte code which can be executed on any platform with a suitable virtual machine. Unfortunately, as noted by Vogels [18] this comes at the expense of performance, with execution times for common high performance computing tasks varying erratically in Java and C# and rarely approaching those available in compiled languages such as C and C++. The performance of these languages has also been shown to vary depending on the quality of the virtual machine implementation, making it unlikely that a simulator written in 8 James McGill - 40793625 Embedded Systems Simulator either of these languages would be able to sustain high simulation speeds on multiple platforms. Kilgore [19] and Thompson and Billawala [20] note that the entities involved in a discrete event simulation are best represented in object-oriented languages in order to provide for maintainability and to allow for future developers to extend their functionality. This, combined with the findings of Phillips and Phillips [17] and Vogels [18], suggests that a simulator will achieve the greatest balance of performance and maintainability if developed in a compiled object-oriented language such as C++. An understanding of the system being simulated is also required before development begins. Documentation of the behaviour of the AT90S8515 AVR microcontroller, selected as a suitable target for simulation, will be extracted from the datasheet provided by Atmel [21]. In order to verify the functionality of this component, its behaviour will be compared to the same processor running as part of the Atmel AVR Project Board used by the University of Queensland to teach embedded systems (Figure 1) [22]. The expected behaviour of additional components will be determined by examining their behaviour and datasheets. Figure 1: CSSE1000 project board 9 James McGill - 40793625 Embedded Systems Simulator 2.4 Testing methodologies Verification of the solution developed will form an integral part of this thesis. By employing structured testing methodologies, accurate claims can be made regarding the correctness of the simulator and components developed, and their suitability for use by developers. Of the various testing methodologies examined, black box testing and system testing are expected to be the most useful. Black box testing is a testing methodology which examines only the expected functionality of a system, ignoring specific implementation details [23]. This makes this method ideal for testing functional implementations of simulator components. Black box testing can also make use of automatically generated test inputs to help identify misunderstood or missing requirements [24]. Testing the software at the software component level [25] allows errors in individual modules to be detected, while employing a level of testing complexity that is achievable within the timeframe of this thesis. System testing, in which the program is tested as a single complete entity, examines the software at a higher level. This ensures that the individual components of the program are able to be integrated in order to produce a stable and correct solution [25]. Automation of these testing processes leads to a reduction in the effort required to perform tests, making it easier to frequently test for, and locate, errors [23,25]. This allows the tests to be used to identify regression errors as they are introduced. However, as noted by Goodliffe [25] manual testing strategies are still required to evaluate the usability of the software. 10 James McGill - 40793625 Embedded Systems Simulator 2.5 Past theses In their treatment of this same thesis topic, Kehl, Nixon and Reynolds [26,27,28] each successfully employed discrete event simulation to functionally simulate the AT90S8515 microcontroller at speeds above 4MHz, thus demonstrating the feasibility of this method. Although the use of C by Kehl [27] and Nixon [28] would have increased efficiency, it led to difficulties maintaining and extending the simulator. In comparison the use of Java by Reynolds [26], while simplifying extensibility, limited the performance of the simulator, requiring compromises in the accuracy of the simulation in order to achieve real-time speeds. The outcomes and limitations of these implementations are expected to play a large role in guiding the design and implementation of this thesis. 11 James McGill - 40793625 Embedded Systems Simulator 3.0 Prior art Given the complexity of modern embedded systems, and the need for embedded devices to be developed both quickly and reliably, it is unsurprising to find that a number of implementations of embedded systems simulators already exist. The following section presents an inspection and analysis of the most relevant of these products, with a focus on those capable of simulating Atmel AVR microcontrollers. This provides a useful survey of simulation methods and feature sets, which are able to serve as an important source of inspiration. 3.1 AVR Simulator IDE AVR Simulator IDE [5] is an entry-level commercial Atmel AVR simulator developed by Oshon Software and licensed for €29 (approximately $40 AUD). The product is able to simulate a wide variety of Atmel chips, although it is currently unable to simulate the more recent additions to the AVR line. AVR Simulator IDE is also able to provide functional simulation of the interaction between an AVR microcontroller and a wide range of analogue and digital peripherals, including UART, I2C EEPROMs and analogue function generators. The main IDE acts as an ActiveX server, allowing the functionality of the program to be extended by 3rd part components. Oshon Software also develop Microchip PIC and Intel 8051 simulators with similar interfaces and feature sets, suggesting that the base code was designed to be extensible with regards to processor instruction sets and functionality, and highlighting the advantages of such extensibility. 12 James McGill - 40793625 Embedded Systems Simulator Unfortunately, AVR Simulator IDE is unable to achieve real time execution speeds, with execution using the simulator being four orders of magnitude slower than execution on the chip itself. This makes debugging of most components extremely time consuming, and prevents developers from easily interacting with the system. The interface (Figure 2) is difficult to navigate, and appears to be targeted at experienced developers. Interpreting the information contained within internal and external data stores such as EEPROM and SRAM requires manual translation from hexadecimal values. Figure 2: AVR Simulator IDE with EEPROM and LCD peripherals enabled. 3.2 Proteus VSM Proteus VSM [4] is a commercial product which allows software verification of both circuit and software functionality through all stages of the design of an embedded system. The product makes use of SPICE mixed-mode simulation, combined with functional models of a 13 James McGill - 40793625 Embedded Systems Simulator number of microcontrollers, to accurately simulate the interaction between external components and microcontrollers in real time. The use of SPICE mixed-mode simulation allows Proteus VSM to accurately model the steady state and transient analogue and digital behaviour of any embedded system. Proteus VSM also provides high-level language debugging facilities for microcontroller code, and is packaged with thousands of peripheral implementations. The product demonstrates the potential for real time functional simulation, and also provides an excellent example of the value inherent in accurate real time simulation of peripherals as it provides the ability to observe the behaviour of components, such as LCDs (Figure 3), by visual inspection, rather than code or register analysis. Individual licenses for Proteus VSM, however, cost in excess of $600 AUD, which makes it unlikely that the product would be adopted for use by students or hobbyists. Additionally, as Proteus VSM is closed source, developers cannot extend the functionality of the simulator. This places a significant limit on the types of embedded systems which can be simulated. Figure 3: Real time simulation of a graphical LCD in Proteus VSM 14 James McGill - 40793625 Embedded Systems Simulator 3.3 Atmel AVR Studio Atmel AVR Studio 4 [3] is an Integrated Development Environment for Windows, provided by Atmel to facilitate the use of their range of 8 bit microcontroller devices. AVR Studio provides a project management system for code development, and integrates with a variety of compilers. AVR Studio also provides debugging functionality which includes a cycle accurate simulation of a number of microcontrollers. Unfortunately, the program is unable to achieve real time simulation, although real time debugging is available with the use of external hardware devices [29]. The simulator also lacks any built-in peripheral implementations, making it difficult to determine the behaviour of software in the context of a larger system. By combining the debugger with an Integrated Development Environment, AVR Studio allows embedded Atmel AVR software to be debugged on a standard PC. The interface also allows the internal state of all memory locations to be read, and provides a significant amount of meta-data for each location (Figure 4). AVR Studio can be extended to incorporate descriptions of additional microcontrollers by editing XML files; however the files must conform to a strict schema and are therefore unable to represent microcontrollers with features beyond those represented by the current line of Atmel AVRs. It also provides a plug-in system which could be used to integrate additional peripherals; however their operation will be limited by the speed of the simulator. The development of these peripherals is also strictly controlled by Atmel, and as such very few have been developed to date. 15 James McGill - 40793625 Embedded Systems Simulator Figure 4: Expanded register view from AVR Studio. 3.4 miSim DE miSim DE [30] is a Java based simulator which is able to support real time simulation of a PIC microcontroller, with several peripherals, at speeds exceeding 4 MIPS. This product demonstrates the ability to write a high performance simulator with many of the features specified in the requirements of this thesis, with a high level Object Oriented language. Peripherals can be added to the system by utilizing a publicly available Java API. This flexibility has been used by third-party developers to extend the functionality of the system by developing additional simulator components. The simulator also supports debugging, as well as assembly and disassembly of PIC programs. miSim DE, however, is limited to use with PIC microcontrollers, and is unable to simulate systems with other microcontrollers, no microcontroller or more than one microcontroller. Although the project used to be open source, the source code to the latest release has not been made publicly available. The source code of older versions, however, may serve as a useful insight into existing microcontroller simulator methods. 16 James McGill - 40793625 Embedded Systems Simulator 17 James McGill - 40793625 Embedded Systems Simulator 4.0 Goals and project requirements The primary goal of this thesis is to produce an implementation of an extensible embedded systems simulator which is able to be used by developers to easily interact with a simulated embedded system. As a demonstration of the functionality of the system, project developed as part of the Introduction to Computer Systems course (CSSE1000) at the University of Queensland will be executed using the simulator. The product presented at the end of this thesis should therefore be capable of a cycle correct functional simulation of the full instruction and register set of the Atmel AT90S8515 microcontroller, as well as several other electrical components which are used in this course. The simulated versions of these components should be able to be connected together to form a complete embedded system. In order to provide feedback to the user that is representative of the manner in which the actual system would perform, the simulator should support simulation of simple embedded systems at real-time speeds. The simulator must also be able to provide a graphical representation of each component in the system, which is updated frequently enough to convey changes in the state of the components, and to maintain responsiveness. In addition to providing representations of simple digital signals, the simulator must also provide representations of open drain (tri-state) drivers and weak signals, as they are used to implement common embedded systems communication protocols such as the 1-Wire Interface [31]. 4.1 Software architecture requirements The final implementation should provide a system which allows both synchronous and asynchronous external components to be easily developed, independently of the core simulator and of each other, and to interact with other components during simulation. These 18 James McGill - 40793625 Embedded Systems Simulator components should be available in a format that is easy to distribute, and each component should be able to be used in multiple simulation projects. 4.2 Required components By the completion of the thesis, a number of peripheral components must be developed in order to demonstrate the functionality of the simulator. These components were selected based on those available to students in CSSE1000, allowing the projects developed in this subject to be used to test the simulator. Specifically, the following peripherals will be implemented: AT90S8515: The AT90S8515 is an 8 bit microcontroller produced by Atmel, which is capable of running at 8 MIPS and which incorporates a number of integrated peripherals [21]. The implementation should include the full instruction set of the AT90S8515, as well as the simulation of its internal peripherals such as timers, counters, PWM, persistent storage via EEPROM and interrupts. External RS-232 Transceiver: A component which emulates the function of an external RS-232 transceiver, able to receive and transmit data using the RS-232 communications standard [32]. The component should be able to detect errors in transmission, including incorrect baud rates. The component should also be able to communicate with applications outside the simulator, to simulate the interactions between an embedded system and an external device, such as a PC. 19 James McGill - 40793625 Embedded Systems Simulator LED Matrix: A 15 x 8 matrix of single colour common cathode LEDs as used by CSSE1000 [33]. This component should incorporate the behaviour of the additional circuits used to drive the matrix, such as the 3 to 8 binary decoder. Speaker: A simple monotone speaker, capable of producing audible tones based on the frequency at which its two inputs are being toggled between digital states. 4.3 Required documentation In order to facilitate the use and future development of this system, it will be necessary to document the solution developed. Documentation of the design decisions used in developing the product will form a part of the final report. Documentation will also be written for those using the simulator, and those who wish to extend it by developing additional components. The source code which makes up the simulator core will be thoroughly commented to ensure that it can be maintained. 4.4 Performance and portability requirements The final product must be able to perform real-time simulations of a digital system composed of a 4MHz Atmel microcontroller and several other components, on a 2.4GHz PC running Windows XP. The product should also be able to be compiled and run under other environments, such as Mac OS X and Linux. This will impose restrictions on the use of software libraries that are only available for a single operating systems, but will allow the program to be accessed by a greater number of users. 20 James McGill - 40793625 Embedded Systems Simulator 4.5 Additional work An additional and optional extension to the project will be the incorporation of debugging functionality for the AT90S8515 component. This will allow software being executed on the Atmel to be debugged in the context of the hardware environment in which it is run. 4.6 Elements considered to be outside scope During the development cycle of a single project, it is likely that the composition of any software will change much more frequently than the hardware on which it is being deployed. The development of a schematic editor is therefore considered outside the scope of the project. Changes to hardware specifications will be made by manually editing project files. Accurate simulation of analogue components, or of the effects of capacitance, resistance and inductance on digital logic, is also considered to be outside the scope of the project. 21 James McGill - 40793625 Embedded Systems Simulator 5.0 Implementation of the simulation framework The simulation framework has been designed to be simple and fast, so that components can be simulated at real-time speeds. Care has been taken to avoid complicating the simulation framework in order to support specific components, instead ensuring that components can extend the simulator’s behaviour with very few limitations. The remainder of this chapter details the architecture and implementation of this framework, and highlights the key design decisions which have made this speed and flexibility possible. 5.1 Architectural overview Simulations are performed based on the logic contained within three classes of objects; Components, Events and Pins. Components define the logic required to simulate a specific digital device, such as a microcontroller or logic gate, Events are used to schedule logic to occur at a particular time in the simulation, and Pins are used to enable Components to interact with each other. The implementations of these classes are discussed in Sections 5.2 – 5.4. The actions of these classes are co-ordinated by a discrete event simulation algorithm, described in Section 5.5. Simulations can be distributed and repeated by loading their details from XML files which implement the simulation project schema, as discussed in Section 5.11. To allow developers to independently define the behaviour of additional devices, Components are loaded dynamically from a cross-platform C++ plug-in. The design challenges which were overcome in order to allow these libraries to be written once, and compiled on multiple operating systems, are examined in Section 5.9. An overview of this architecture is presented in Figure 5. 22 James McGill - 40793625 Embedded Systems Simulator Connection Pin .. . .. . Component Pin Component Pin Pin Plug-in Plug-in Plug-in boundary Event Event Event Event Graphical User Interface Event Event list Repeated Event List Discrete Event Simulator Figure 5: Overview of simulator architecture 5.2 Components The logic required to simulate and describe a digital device is implemented by extending the abstract Component interface. In addition to defining the required structure of a Component object, the Component class provides an API, which can be used to manage interaction with the simulator framework, Pins, and component meta-data. Components are expected to facilitate functional, rather than gate level, simulation of an embedded device. This allows the behaviour of a device to be abstracted, reducing computational complexity. 23 James McGill - 40793625 Embedded Systems Simulator Components are invoked directly by the simulator framework on initialization, when the simulation is started, paused or stopped, and in response to user interaction (such as clicking on the GUI). As these events occur infrequently, the majority of a Component’s execution is expected to be invoked indirectly by Event objects, in response to a scheduled event being executed, or by Pin objects in response to a change in an input value. 5.2.1 Providing a graphical representation of a components state Component objects provide logic to render a graphical representation of a component’s current state, using the Cairo graphics library [34]. A number of rendering options, including the Gimp Drawing Kit (GDK) [35], Cairo, and using pre-rendered graphics, were examined. Cairo was chosen as it provides a cross platform method of drawing complex vector and raster graphics onto a variety of image surfaces, including the GUI. The Cairo API is richer than that offered by GDK [36], and unlike pre-rendered graphics, allows the component representation to be dynamically adjusted in response to changes in state. The graphical representation of each Component is redrawn only in response to a change in the components state, ensuring that the least amount of processing time possible is used to maintain an accurate graphical representation of the system. 5.3 Events Components are able to schedule logic to be executed at a specific time by implementing concrete versions of the Event interface. Events are executed in a monotonically increasing order based on the time at which they are scheduled, which ensures that simulations are stable and deterministic. Ordering of events is performed by a discrete event simulation algorithm, discussed further in Section 5.5. 24 James McGill - 40793625 Embedded Systems Simulator 5.4 Pins Within a simulation project, as in a physical circuit, components are able to interact by modifying the values on their output pins, and responding to changes in the values of their input pins. The values of pins, and the connections between them, are managed by Pin objects, each of which is expected to be a member of a single Component. To ensure consistency, components must interpret the values of pins according to the protocol outlined in Table 1. Value / range Meaning 0 Strong logical 0 1 Strong logical 1 2 Tristate (Disconnected) 3 Weak logical 0 (Pull down) 4 Weak logical 1 (Pull up) Table 1: Pin value protocol. Adhering to this protocol, and ensuring that each Component’s behaviour is consistent with that of the physical device which it represents, allows components developed by different parties to interact correctly. A decision was made not to allow arbitrary values on pins, which could be used to pass messages between components, as it prevents component re-use. The protocol allows for the representation of strong, weak and tri-state drivers, in order to allow communication using open drain protocols such as OWI [31], and allows pins to be configured as inputs, outputs or both. When a pin is driven by multiple signals, the net pin value is automatically resolved by the simulator. 25 James McGill - 40793625 Embedded Systems Simulator Each Pin’s value is stored as 16-bit value, allowing the protocol to be extended in the future. This could be used, for example, to allow simple analogue devices to be simulated. Each Pin implements both a Concrete Subject and Concrete Observer from the Observer design pattern [37], which is used to update the value of a Pin when the value on a Pin to which it is connected changes. If the value of a Pin changes in response to an update message, a second update message will not be issued. This increases the speed of the simulation by preventing cyclic notification (Figure 6) but requires that transitive connections be avoided (Figure 7). This is achieved as a result of using electrical nets to specify connections in the simulator project format. Pin A Value: 0 1 aVasd asd as a Notification: Value = 1 Notification: Value = 1 Pin B Value: 0 1 aVasd asd as a Figure 6: Cyclic notification problem. The two components will continue to notify each other indefinitely unless terminated. Val Pin A Val Pin B Pin A Pin B Pin C Pin C (a) (b) Figure 7: Transitive pin connections. The transitive connection between Pin B and Pin C in (a) must be explicitly defined, as in (b), for correct simulation. 26 James McGill - 40793625 Embedded Systems Simulator Concrete Pin objects are able to implement custom logic which is executed in response to a change in value. This is used in the AT90S8515 component to implement external interrupts and in digital logic gates to re-evaluate their output in response to external stimulus. 5.5 Discrete event simulation Simulations are co-ordinated using a discrete event simulation algorithm, which models the system by executing the logic contained within Event objects in a strict time order. This algorithm was selected over alternatives, such as statistical simulation, as it can be used to produce deterministic simulations, allowing the behaviour of the system to be accurately evaluated. The implementation of the event set, used to order events within the simulator algorithm, builds upon the work of Goh and Thng [16] on the use of multiple lists to improve event set performance. The majority of events are stored in a priority queue, ordered by the simulator time at which they are to be executed, and are added and removed as required. As it is expected that the simulator will often be used to simulate synchronous components, a separate event set is provided for events which are repeated regularly (Figure 5). Events added to the repeated event set need only be added once, and are then executed at regular intervals based on their clocking speeds. Use of this technique reduces the significant overhead required to reschedule an event each time a synchronous device is clocked while retaining the flexibility and range of a single event list. Empirical testing has shown that the use of a separate queue for synchronous events accounts for a 150% – 200% speedup in simulations involving the AT90S8515 microcontroller. An important property of this solution is that it is able to support multiple synchronous components by polling the regular event list at an interval equal to the Greatest Common Divisor (GCD) of the repeating periods of the components in the list. This 27 James McGill - 40793625 Embedded Systems Simulator solution incurs very little overhead when a large GCD can be found, but deteriorates as the GCD approaches 1. The inner loop of the simulator is responsible for interlacing events from the two event sets, and ensures that events are always executed in the correct order. 5.5.1 Enqueuing events Events are scheduled by passing concrete instances of the Event interface to the simulator core using the simulator API. This is expected to occur on initialization, in response to the execution of an event, or as a result of the change in the value of a pin. The type of event queue to which the Event object is to be added – repeated (synchronous) or normal – is specified by the API call. 5.5.2 Simulator timestamp Each event is scheduled with a resolution of one deca-picosecond, stored as a 64 bit unsigned integer which measures the simulation time elapsed since the start of the simulation. This allows simulations between ten picoseconds and 5.85 years to be performed. A resolution of 10 picoseconds allows a synchronous component to be clocked at 100 GHz, while still allowing the reliability of a long running (5.85 year) embedded system to be examined. Although both a higher resolution and longer simulation times would be desirable, the associated decrease in performance and increase in complexity required to store the simulator as a user-defined data type was considered too great a cost. The simulator timestamp can also be used by Component and Pin objects to verify the timing characteristics of digital devices, such as setup and hold times. 28 James McGill - 40793625 Embedded Systems Simulator 5.5.3 Memory management To avoid the computational expense of allocating and freeing the memory used to store an Event, Event objects are designed to be allocated once and re-used often. The simulator is specifically designed to allow an Event to be re-scheduled, even while being executed, which allows simulations to be performed which require no explicit memory management during execution. 5.6 Real-time execution A simulation is considered to be executed at real-time if the current value of the simulator timestamp is constrained to be equal to the amount of wall clock time that has elapsed since the simulation began. This constraint can only be met if it is possible to carry out the simulation faster than real-time; however the simulation algorithm is guaranteed to produce correct and stable simulations regardless of CPU speed. By removing the real-time constraint, low activity simulations can be carried out at higher speeds, providing an efficient method for testing the long term reliability of an embedded system [25]. As the simulator is not designed to run on a real-time operating system, small fluctuations in speed have been deemed acceptable. 5.7 Error reporting The simulator API provides a mechanism for Components to report errors, such as invalid inputs or timing violations. These errors are aggregated and logged during the simulation, and can be viewed from a log file, or from the graphical user interface once the simulation is complete. This offers a significant advantage over traditional methods of debugging 29 James McGill - 40793625 Embedded Systems Simulator embedded systems, as Components can automatically detect and report common errors and timing violations. 5.8 Graphical user interface A Graphical User Interface (GUI) is used to allow users to control the simulation, and to display the current state of each component (Figure 8). The use of graphical representations of components allows users to interact with components in a way that is consistent with a physical device; for example, an LED can be observed to be lit or unlit, and a switch can be pressed using a computer mouse. The GUI is created using the GTKmm C++ bindings to the Gnome ToolKit libraries [38]. This library was selected over other cross platform alternatives such as wxWidgets [39] and Qt [40] as it is open source, actively maintained, and was found to be the easiest to use. The GUI uses the Model-View-Controller pattern [37] to allow the simulator to be controlled, and its current state represented in the GUI, while allowing re-use of the simulator logic with alternate user interfaces. Components may also spawn additional GUI windows, allowing the representation of additional information that is not easily included on the main user interface. To ensure that the GUI remains responsive, but does not consume too many resources, it is executed on its own, lower priority, thread. 30 James McGill - 40793625 Embedded Systems Simulator (a) (b) Figure 8: Simulator graphical user interface. Showing the simulator log (a) and displaying the current state of 8 LEDs and 8 switches (b). 5.9 Cross platform plug-in architecture The simulator makes use of a cross platform plug-in architecture in order to achieve the goal of allowing additional components to be developed and distributed independently of each other, and of the core framework. The plug-in framework implemented is based on the work of Sayfan [41] and has been extended to provide explicit operating system versioning, fast messaging across the plug-in boundary by using explicit function calls in favour of message passing, and faster runtimes by focusing on dynamic loading of C++ objects, and discarding support for C objects and static compilation in released components. Each plug-in provides a concrete implementation of a Component, as well as supporting Pin and Event objects. 31 James McGill - 40793625 Embedded Systems Simulator Plug-in libraries are expected to be stored in a single folder, and are enumerated when the simulator is initialized. This provides a simple method of redistributing and installing components. The Gnome Module library[38] is used to load the dynamic libraries and execute their exposed C methods independently of the host operating system and library format. As Unix-like operating systems provide no direct support for exporting C++ class definitions as part of a dynamic library, the C++ Component objects used are created and destroyed using a C API, which can be safely exported on all target operating systems. The simulator uses the definition of the Component interface to interpret the structure of the object returned by the C API. The simulator and plug-in must therefore have a common definition of the Application Binary Interface (ABI) for a Component. A common ABI is unlikely if the simulator and plug-in are compiled with different compilers, or different versions of the same compiler. Furthermore, changes to the Component class structure will necessitate recompilation of all plug-ins. While undesirable, this is expected to happen very rarely as the component API is now finalized. To allow the plug-in to be compiled independently from the simulator framework, it must not depend on aspects of that framework. Each component therefore only depends directly on a small library which defines the Component, Event and Pin classes. Components communicate with the core simulator framework using a C API which is passed as a set of function pointers to each plug-in upon instantiation. The use of function pointers allows the component to be compiled with only the definitions of the API function prototypes, without depending on their implementations. 32 James McGill - 40793625 Embedded Systems Simulator 5.10 Automatic plug-in documentation generation As documentation is a key goal of this thesis, the Component interface was carefully designed so that the implementer of a class extending Component must provide enough information to fully document that classes use as a simulated component. This information has been used to automatically generate navigable HTML documentation for each component (Figure 9) which is expected to benefit the authors of simulator projects. Switch A simple switch, with an active high output. Properties Name Description Default value type Type of switch: Push or Toggle Toggle Pins Name Index Output 0 Figure 9: Documentation automatically produced for the switch component. 5.11 Persistence of simulation properties using simulation projects A simulation project is an XML file format used to store the information required to enable a system to be simulated. The use of simulation projects ensures that the system to be simulated can be easily shared; as all the information required to reproduce a simulation, given a suitable set of plug-ins, is encapsulated within a single file. The project stores the names and 33 James McGill - 40793625 Embedded Systems Simulator properties of the components involved in the simulation, the connections between these components, and the position of each component on the user interface. Initially projects were stored in a custom serialization format, however this proved to be error prone, and difficult to maintain. XML [42] is now used as the basis for the simulation project format as it is a well understood serialization language, with support for parsing, writing and verification available in multiple programming languages. This support ensures that additional tools which would interact with the format, such as an interactive editor, can easily be developed if required. XML is also human readable and editable, allowing projects to be developed using only a text editor, an important consideration as developing an interactive project editor is outside the scope of this thesis. As the size of projects is not expected to be a concern, the verbosity of XML was determined to be an acceptable trade-off. Other structured formats, such as JSON [43] and Yaml [44] were considered, but were found to lack mature C++ language support. The simulator project format is fully described by the XML schema in Appendix A. 5.11.1 Loading simulation projects Simulation projects are loaded using an instance of the XmlParser class, which uses the cross platform TinyXML [45] library to parse the XML project file. The TinyXML library provides good error detection and robustness when parsing invalid documents, with less implementation overhead than other XML libraries examined. 34 James McGill - 40793625 Embedded Systems Simulator 35 James McGill - 40793625 Embedded Systems Simulator 6.0 Implementation of plug-in components A significant amount of the work undertaken during this thesis has involved the development of plug-in components. These components have been developed in order to verify the functionality of the simulator, and with a particular focus on making it useful to students enrolled in the Introduction to Computer Systems course at The University of Queensland. The remainder of this chapter provides a summary of the components implemented, and the key design decisions made during their implementation. 6.1 Atmel AT90S8515 8-bit microcontroller To demonstrate that the simulator is able to simulate complex synchronous devices at high speeds, a plug-in has been developed which implements the functionality of the Atmel AT90S8515 8-bit microcontroller. The simulated device is able to execute binary files, which have been compiled for the AT90S8515, without modification. The simulated device also implements many of the peripherals found on the real device, such as timers, counters, interrupts, EEPROM and USART. 6.1.1 Common AVR functionality The AT90S8515 takes advantage of object-oriented design to partition the implementation into elements which are specific to the AT90S8515, elements which are common between all Atmel AVR (AVR) microcontrollers (AVRCore) and elements which are common to a family of AVR microcontrollers (AVRPeripheral). Composition of these classes allows implementations of additional microcontrollers in the AVR range to be developed with minimal effort (Figure 10). 36 James McGill - 40793625 Embedded Systems Simulator 1 1 AVR Core 1 1..N AVR Peripheral AT90S8515 Composition Figure 10: AT90S8515 class architecture As all AVR microcontrollers implement some subset of the Atmel AVR instruction set [46], the interpretation and execution of instructions is performed by the AVRCore. The AVRCore also provides an API which can be invoked by a specific AVR implementation, in this case the AT90S8515, to access registers and memory, detect interrupt conditions and to provide a graphical user interface and debugging capabilities. 6.1.2 Instructions Programs written for Atmel AVR microcontrollers are compiled to 16 and 32 bit binary opcodes. To enable compiled programs to be executed, a set of AvrInstruction classes, have been developed to implement the functionality of each instruction. AvrInstruction classes also provide meta-data to facilitate disassembly and debugging. Each AvrInstruction class is able to partially disassemble an AVR binary file, using a Factory method [37] to create an instance of the AvrInstruction object for every instance of that instruction in the binary file. As all AvrInstruction objects are instantiated before a simulation begins, pre-processing can be used to perform the processing required to identify an instruction, extract operands from the instructions op-code (Figure 11), and to interpret these operands. Pre-parsing the binary input, rather than decoding instructions as they are run, 37 James McGill - 40793625 Embedded Systems Simulator produces faster simulation speeds by reducing the overhead incurred while executing each instruction. Once resolved, AvrInstructions are stored in an array, allowing them to be indexed using the current value of the microcontrollers program counter. Instructions which occupy more than one 16-bit word are allocated multiple slots in the array in order to preserve addressing. 0010 11rd dddd rrrr Figure 11: Demonstration of operands within an opcode (MOV opcode) The 5 bit values for the source (r) and destination (d) register are interlaced, complicating extraction. 6.1.3 Registers and data storage The hardware functions of AVR microcontrollers are controlled by manipulating the values of 8 bit Input/Output (I/O) registers, while working registers and SRAM are provided for volatile data storage. The AVRCore class provides an API which segments the various types of memory by address (Figure 12), allowing instructions to read from and write to memory in a consistent manner. Each I/O register is a concrete implementation of the AvrMemory interface, allowing each to implement custom logic in response to data being written or read. This is used to implement the hardware control functionality of I/O registers, such as copying data written to a PORT register to the 8 Pin objects which represent the pins of that port. 38 James McGill - 40793625 Embedded Systems Simulator Working registers and SRAM (excluding mirrored I/O register locations) are simply used to provide storage. An array of octets is used to provide a low level, and therefore efficient, method for storing and accessing this data. Instructions which are known to only access working registers can achieve faster execution speeds by bypassing the memory API and accessing these locations directly. 32 General Purpose Working Registers $0000 - $0001F 64 I/O Registers $00020 - $0005F Internal SRAM (8 x 512) $0060 - $025F External SRAM (8 x 64K) $0260 - $FFFF Figure 12: AVR address segments for an AT90S8515. The size of each segment is passed to the AVRCore upon initialization. 6.1.4 Automatic generation of skeleton classes To reduce the time required to implement AvrInstruction and AvMemory objects, python programs have been written which produce skeleton C++ classes from Django [47] templates (Appendix B) for each instruction and register implemented by a selected AVR device. The information required to produce each class is automatically extracted from Atmel datasheets. The skeleton classes contain instruction and register meta-data, used for debugging, as well as the pre-processing and disassembly code for each AvrInstruction object. The use of these 39 James McGill - 40793625 Embedded Systems Simulator programs is estimated to have reduced development time by several weeks and to have significantly reduced the number of errors that would have occurred if manually implementing the classes. 6.1.5 Interrupts Hardware interrupts are used by AVR microcontrollers to provide an immediate response to a hardware condition by causing execution to jump to a specific address. The AVRCore component is designed to isolate the implementers of additional AVR microcontrollers from the complexity of detecting interrupt conditions, and ensures that interrupts are executed at the correct time, in the correct order, and with the correct cycle delay. An interrupt is triggered if the global interrupt flag in the status register is set, and both the interrupt’s flag and enable bits are set (Figure 13). The AVRCore takes advantage of this architecture, and only evaluates an interrupt when the value of one of the registers that it is linked to is changed. In order for an I/O register to be registered with the AVRCore as an interrupt status or mask register, it must inherit from the AvrInterruptRegister interface, which provides the functionality needed to allow the interrupt manager to act as an observer of the register. If multiple interrupts are triggered simultaneously, their priority is used to ensure that they are executed in the correct order. It remains the responsibility of the microcontroller specialization to set interrupt flag bits at the appropriate time, for example to signify a timer overflow. 40 James McGill - 40793625 Embedded Systems Simulator I T H S V N Z C Global status register (SREG) Flag Status register Interrupt triggered Enable Corresponding mask register Figure 13: Conditions required for an interrupt to be triggered. 6.1.6 Cycle correct execution The AVRCore is designed to produce cycle correct simulations, which ensures that execution of every instruction consumes the correct number of CPU cycles. During testing, it was discovered that delaying a certain number of cycles after each instruction was insufficient, as on the device itself the result updates to memory locations are performed on the final cycle. This has been demonstrated to lead to errors in simulation when an instruction modifies a location in the same cycle as an internal peripheral. The AvrInstruction interface therefore requires that all instructions be able to calculate the number of cycles that they will use prior to execution, even when that number can vary. 6.1.7 Status register As part of the execution of an instruction, it is likely that the microcontroller’s global status register will need to be updated. This register information about the result of the most recently performed arithmetic operation, such as whether a negative result was produced [21]. These conditions are primarily used to evaluate the result of branching instructions. The 41 James McGill - 40793625 Embedded Systems Simulator AvrInstruction class structure separates the logic required to update the status register from the logic required to execute the remainder of the instruction. This design, inspired by the work of Gauthier and Jerraya [10], allows computation of the status register value to be delayed until the value is required by a branching instruction. This ability is not currently used, but is expected to reduce the average number of computations required to execute an AVR instruction if enabled. 6.1.8 Graphical user interface and debugging functionality In addition to simulating the behaviour of an AVR, the AVRCore also provides debugging and introspection functionality in order to make testing software using the simulator easier than testing on the physical device. A graphical user interface is used to show program disassembly, and provides the ability for users to set breakpoints, step through code and to observe the value of any register or memory location (Figure 14). Breakpoints are stored as a property of each AvrInstruction instance, allowing O(1) detection of breakpoint conditions and allowing a breakpoint to be set on every line. Watched variables are updated only when execution is paused or stopped, and therefore have no impact on the simulation speed. The meta-data included in AvrMemory objects is used to allow registers to be watched by name (e.g. SREG) in addition to by address (e.g. 63). The AvrCore is also able to parse LSS and LST files, which provide a simple mapping between the original source code (in assembly or C) and the compiled binary. This is used to display comments, as shown in Figure 14, and to provide a mapping between lines of code and compiled instructions. 42 James McGill - 40793625 Embedded Systems Simulator Figure 14: The AVRCore debugging window. 6.1.9 Internal AVR peripherals A large amount of the functionality offered by a specific family of AVR microcontrollers is performed by internal peripherals, such as Timers/Counters and USART. To ensure that these features can be re-used by implementations of other devices in the same family, peripherals are implemented by inheriting from the AvrPeripheral interface. Each peripheral can register concrete implementations of AvrMemory objects with the AVRCore, and can implement logic to be executed on each clock cycle. In addition to promoting code re-use, this provides a simple way to partition the complex functionality of a microcontroller. Concrete AVRPeripheral objects have been developed that implement the complete functionality of the 8 bit Timer/Counter, 16 bit Timer/Counter with PWM, external interrupts 43 James McGill - 40793625 Embedded Systems Simulator and EEPROM peripherals of the AT90S family of AVR microcontrollers. A cycle and pin correct USART peripheral has also been developed, however support for 9-bit transfers is not yet implemented. All interrupts associated with these peripherals have also been implemented, using the interrupt functionality provided by the AVRCore. 6.1.10 EEPROM Peripheral In addition to allowing the runtime storage of data, the EEPROM peripheral is able to serialize data to and from Intel Hex files. Use of this format allows the EEPROM state to be transferred between the compiler, simulator and physical devices as required. The peripheral also uses the ability to execute logic on each clock cycle in order to accurately implement the complex EEPROM timing requirements. 6.1.11 AT90S8515 Implementation The advantage in the architecture used to implement simulated AVR components (Figure 10) is that very little additional work is required to implement a specific microcontroller in the AVR range, including the AT90S8515. The only significant tasks performed by the AT90S8515 component are to initialize a instance of the AVRCore object with the correct memory boundaries, define each of the interrupts, provide implementations of any registers not associated with an AVRPeripheral object and instantiate and register Pin objects for each pin on the device. The remainder of the AT90S8515’s functionality is provided by compositing the peripheral objects described above. Implementing additional microcontrollers in the AVR range is expected to be equally simple. 44 James McGill - 40793625 Embedded Systems Simulator 6.2 TCP/IP based RS-232 Transceiver To provide a method for external systems to communicate with devices under simulation, a component has been developed which is able to transfer data between a TCP/IP connection and simulated devices which implement the RS-232 protocol. This allows developers to simulate the behaviour of a serial connection to a PC by providing a connection between the simulator and any program with TCP/IP support. Consideration was given to using a software serial null-modem implementation to allow the simulator to communicate with any program with serial, rather than TCP/IP, support; however this was found to be too complex to implement on multiple operating systems. The component uses the simulator timestamp to calculate the baud rate at which data is arriving on the component’s serial receive pin, and to compare it to the expected baud rate. If there is a baud rate mismatch, the component uses the simulator error API to report it. This provides a simple mechanism to detect and debug a common problem that can be difficult to identify on a physical device. 45 James McGill - 40793625 Embedded Systems Simulator (a) (b) Figure 15: Detection of incorrect baud rates during simulation. Error notification (a), and the reporting of that error in the simulator log (b). 6.3 Speaker A speaker component has been developed in order to verify the PWM implementations within the Timer/Counter peripheral, and for use in the Introduction to Computer Systems subject at the University of Queensland. The component plays audible notes based on the frequency at which the difference between the logical signals on its two pins changes. The audible note is produced by quantizing the frequency to the nearest Musical Instrument Digital Interface (MIDI) note, using the formula presented in Figure 16, and by playing that note using the cross platform PortMidi MIDI library [48]. MIDI was selected as it is able to be implemented cross platform, and, unlike sampled formats such as WAV, allows notes to be produced at a single frequency with little overhead. The use of a CPU timer to drive a PC speaker was also considered, however the 46 James McGill - 40793625 Embedded Systems Simulator output of a CPU timer, unlike MIDI, cannot be re-routed to headphones, muted, or used on computers without motherboard speakers. 𝑀𝐼𝐷𝐼 𝑁𝑜𝑡𝑒 𝐼𝐷 = 57 + 12 𝑙𝑜𝑔2( 𝑓 ) 440 Figure 16: Formula for conversion between frequency (Hz) and MIDI Note ID 6.4 Additional components In addition to the components discussed above, the following simulated components have been implemented and demonstrated to work: LED – A single colour Light Emitting Diode which can either be lit, or unlit. Toggle switch – A switch which can be toggled on or off using a computer mouse. T flip flop – A self clocking T flip flop, used to demonstrate the ability to safely chain components which update simultaneously. Back-lit Momentary switch – A back-lit switch which is automatically released after a period of 2 seconds. This component was developed to demonstrate the various features offered by the Component API. Seven segment display – A seven segment display with an integrated Binary-coded decimal to seven segment decoder. LED Matrix – An N x M LED Matrix driven by N column signals and log2(M) row signals via a multiplexer. LCD - A two-line, 80 character LCD (Figure 17) which implements the HD-44780 LCD controller instruction set (except custom graphics). This component has an 47 James McGill - 40793625 Embedded Systems Simulator integrated pull up-resistor on the enable line, which has been used to demonstrate the ability to simulate open-drain communication protocols. Figure 17: Simulation of an 80 character LCD, driven by an AT90S8515 microcontroller. 48 James McGill - 40793625 Embedded Systems Simulator 49 James McGill - 40793625 Embedded Systems Simulator 7.0 Verification of solution By comparing the solution developed to the requirements outlined in Chapter 4, the correctness and completeness of the simulator can be established, and a measure of its suitability for distribution developed. This chapter details the methods that were used to test the capabilities of the simulator and includes a discussion of the results of these tests in the context of the goals of the thesis. The management of the project is also examined to evaluate the extent to which it contributed to the outcomes of the project. 7.1 Testing methodologies The software and associated plug-ins have been carefully verified using both manual and automated testing. This has allowed accurate results regarding the simulators capabilities to be derived. 7.1.1 Testing of the complete system During the development of the simulator, testing against a small set of simulator projects was used to identify regression bugs in the complete system and to provide an indication of the simulator’s features, correctness and completeness. The projects were primarily drawn from a set of practical exercises employed by the Introduction to Computer Systems subject at the University of Queensland, and had visual and easily verifiable outputs. This form of testing was also useful in identifying usability issues in the user interface. To ensure consistency in testing, a detailed testing plan was produced for each test, an example of which is included in Appendix C. Appendix D provides an overview of the tests which were created to test specific features of the simulator framework, as well as to test the behaviour of the plug-ins developed. 50 James McGill - 40793625 Embedded Systems Simulator System testing was initially performed manually; however this was both time consuming and repetitive. To reduce the effort required to test the solution, a python framework for automated testing of the simulator GUI has been developed using the AutoIt Windows COM library [49]. The framework provides a simple API which facilitates interaction with the user interface, as well as the ability to test the state of the simulator by comparing the GUI (as an image) to an expected state. Any differences identified are highlighted and saved for review (Figure 18), allowing unsupervised testing. Actual Expected Figure 18: Simulator error, as identified by the automated project testing framework. The framework has been used to implement each of the tests outlined in Appendix C. In addition to reducing testing effort, automated testing has allowed a single project to be simulated hundreds of times within a few hours. This was an important factor in allowing concurrency errors, which occurred infrequently, to be identified and remedied. 51 James McGill - 40793625 Embedded Systems Simulator Unstructured manual tests have also been performed, in order to identify errors that manual tests may routinely miss. These tests primarily focused on the system’s ability to cope with unexpected states, such as performing simulations with invalid inputs. 7.1.2 System benchmark In addition to structured testing of the complete system, specific testing was carried out at the conclusion of the project in order to obtain accurate measurements of performance. An implementation of Tetris, developed for the AT90S8515 by a student as part of the Introduction to Computer Systems course at The University of Queensland is used as a performance benchmark. The program is designed to be executed on a 4MHz AT90S8515 microcontroller, in a system consisting of the microcontroller, a 15 x 8 LED display, a piezoelectric speaker and a serial connection to a PC terminal (Figure 19). The number and complexity of these plug-ins is consistent with the project goal of achieving real-time simulations in a system with a single microcontroller and several other components. The particular implementation of Tetris chosen was selected as it uses all of the internal peripherals developed for the simulated AT90S8515 component. The compare match and PWM capabilities of both timers are used to play music and to refresh an LED matrix, while USART is used to refresh a terminal display at regular intervals. EEPROM is used to store and load high scores, and to load music data. This has been determined to be a realistic example of a complex microcontroller application, and therefore suitable for use as a benchmark. 52 James McGill - 40793625 Embedded Systems Simulator Figure 20 shows the benchmark system being run on the simulator, connected via TCP/IP to Hyper Terminal to simulate an Atmel to PC serial connection. The results of executing this benchmark are presented in Section 7.2.2. Figure 19: Hardware used by the Tetris benchmark. Figure 20: Simulation of the Tetris benchmark. 53 James McGill - 40793625 Embedded Systems Simulator 7.1.3 Automated testing of the Atmel AT90S8515 plug-in An automated framework has been developed to provide a more accurate indication of the AT90S8515 plug-in’s correctness than can be determined using manual or system testing. Although manual testing of a microcontroller can be used to identify that it is not operating correctly, it provides no mechanism for accurately locating the source of the error. It is also possible for a program being executed on the simulated microcontroller to eventually produce the correct set of outputs without following the same execution path that it would on the physical device. The framework developed overcomes these issues, allowing errors in the implementation of the plug-in, and their effects, to be identified with an accuracy of a single execution step. The framework loads an implementation of an AVR microcontroller as a simulator plug-in and executes a compiled AVR binary on the component. After each execution step, the state of the simulated microcontroller, defined by the current values of every working register, I/O register, SRAM register and the current value of the program counter, is compared to an expected state. Any divergence in state can be identified immediately, allowing not only the step at which the error occurred to be identified, but also the exact effect of the error on the microcontroller’s state. Figure 21 shows the output of the framework after identifying an error in the execution of the NEG instruction. 54 James McGill - 40793625 Embedded Systems Simulator … [AvrCore::core_clock] Executing 0x0B: NEG 0x10 [AvrTestRunner::validate_] Reg (10): Expected: 0, found: ff at step 11 [AvrTestRunner::validate_] I (3f): Expected: 2, found: 35 at step 11 [AvrTestRunner::run] Finished executing test: Test CSSE1000 Prac 4. [AvrTestRunner::run] 2 errors from 20 steps. [main] 0 / 1 TESTS PASSED. Figure 21: Output from the AVR Testing Framework. In order to run the tests, the expected state of the microcontroller at each stage of execution must be known. This information can be captured from the physical device using the JTAG or DebugWire debugging protocols. For older microcontrollers, where no such protocol is available, a software simulator, such as AVR Studio, can be used to produce an appropriate set of reference states. To facilitate this, a python script has been written to automatically capture the state of a program being executed in AVR Studio (Appendix F). The state is stored as a set of Intel Hex files, which are parsed by the simulator. The limited amount of information available about AVR microcontrollers means that a number of assumptions must be made during the implementation of the simulator plug-in. The ability of this black box testing method to empirically test these assumptions, by comparing the components state to an implementation which is known to be correct, is one of its greater strengths. The testing framework is also able to execute a simple scripting language, allowing the testing procedure to be modified to support the testing of partial implementations, and against a set of inputs which are known to contain errors. The commands available in the scripting language 55 James McGill - 40793625 Embedded Systems Simulator are described in Appendix E. Automated tests have been developed to test the implementation of the AVR 8-bit instructions available to the AT90S8515, as well as hardware features of the device such as the Timer/Counter 0, USART, EEPROM and interrupt peripherals. 7.2 Results The testing methodologies discussed in Section 7.1 have been used to derive accurate measures of the software’s completeness, stability and performance. These results are presented in the following sections. 7.2.1 Manual testing of components and simulator framework As of the time of submission, all system tests pass completely. As part of this testing, the simulations have also been verified to convey the state of the system under simulation in a way that is perceptually similar to real devices, and to run at speeds which are not perceptually different from the speed at which the real devices would run. No problems have been identified with the usability of the graphical user interface. 7.2.2 Performance The speed of simulation has been shown, as expected, to vary significantly based on the components involved in the simulation. Profiling of the benchmark application shows that the underlying simulator framework accounts for less than 20% of the discrete event algorithm’s execution time, with the remainder being a function of the complexity of the components being simulated. When real-time simulation is disabled, a system consisting of only an AT90S8515 component is able to run at 350 – 400% of real time on a 2.4 GHz PC running Windows XP. In comparison, the Tetris benchmark, running on a 4 MHz AT90S8515, runs at an average of 300% of real-time on the same CPU. The relatively small decrease in 56 James McGill - 40793625 Embedded Systems Simulator performance compared to an AT90S8515 only system is consistent with the complexity of the AT90S8515 plug-in when compared to other plug-ins. When real-time simulation is enabled, the simulation speed is constrained to approximately 100% of real time. Figure 22 plots the difference between simulation time and real-time (wall clock time) over a period of 150 milliseconds, measured while running the benchmark application. On Windows XP, the error between simulator time and real-time oscillates between ±2ms with a mean of 0ms. Mac OS X is shown to have a much smaller error, with the error oscillating between 0ms and 1ms. Figure 23 demonstrates that this error is approximately stable over the lifetime of a simulation, although a small increase in error is observed at 3 seconds, after which the system rapidly stabilises. These observations are consistent with measures taken while simulating other systems. Error (simulator time - real-time) when simulating the Tetris benchmark system 5 Windows XP Mac OS X 10.5 4 Error (ms) 3 2 1 0 -1 -2 -3 -4 -5 0 50 100 Simulator time elapsed (ms) Figure 22: Error between simulation time and wall clock time over 150mS. 57 150 James McGill - 40793625 20 Embedded Systems Simulator Error (simulator time - real-time) when simulating the Tetris benchmark system Windows XP Error (ms) 10 0 -10 -20 0 1000 2000 3000 4000 5000 6000 7000 8000 9000 Simulator time elapsed (ms) Figure 23: Error between simulation time and wall clock time over 9 seconds 7.2.3 Stability Real-time simulation speeds are not expected to be achievable for all systems; however the simulator framework guarantees that simulations will remain stable regardless. Manual testing has been used to verify this assertion, by inserting artificial delays to lower simulation speeds to less than 1% of real-time. Manual testing has been used to verify that all tested projects (Appendix D) function correctly at this speed. 7.2.4 AT90S8515 At the time of submission, the AT90S8515 plug-in passes all tests in the automatic testing suite. Instruction coverage has been measured (Figure 24), demonstrating that every implemented instruction is called and tested at least once by the testing suite, and that many instructions are tested several hundred times. The cycle accuracy of each instruction has also been verified by monitoring the value of Timer/Counter 0, configured to increment once each CPU cycle, while running each instruction. 58 James McGill - 40793625 Embedded Systems Simulator Hardware features such as Timer/Counter 1 cannot be tested using the automatic framework, as correct values for their state during program executions could be not be obtained. These features have been tested using a combination of manual testing, and indirectly by sharing code with features which can be tested (such as Timer/Counter 0). Instruction coverage histogram 80 70 Frequency 60 50 40 30 20 10 0 -50 0 50 100 150 200 250 300 350 400 450 500 + Instruction coverage (number of times executed) Figure 24: Frequency distribution of total instruction coverage (calls) over all automatic tests. 7.3 Functionality and deliverables In addition to being used to examine the abilities of the simulator framework, manual testing has been used to verify that the simulator meets the functional requirements identified in Chapter 4. The non-software deliverables developed, such as documentation, have also been examined in the context of these goals. 59 James McGill - 40793625 Embedded Systems Simulator 7.3.1 Required components All required components, outlined in Section 4.2, have been implemented and demonstrated to function correctly using both manual and automated testing. In addition, a number of additional components have been implemented, as detailed in Section 6.4. These additional components significantly extend the usefulness of the simulator. The optional goal of implementing an AT90S8515 graphical debugging environment has also been achieved (Section 6.1.8). 7.3.2 Maintainability Care has been taken to ensure that the code base is able to be maintained in the future, without requiring the input of the author. Documentation, in the form of comments, is used throughout the code to explain important implementation choices and complicated segments of code. Additionally, all code written conforms to a strict style guide and uses clear names for variables and functions. Unfortunately, some elements of the code base, particularly plug-in components, have few comments. These components will need to be documented before they can be expected to be maintained. 7.3.3 Documentation The development of documentation, in order to facilitate the use and future development of the simulator formed an important goal of this thesis. A significant amount of time has therefore been spent ensuring that sufficient documentation is available for both end users and developers. This document is expected to be the starting point for developers hoping to extend the simulator framework or implement additional AVR components. In addition, a detailed 60 James McGill - 40793625 Embedded Systems Simulator tutorial has been written which outlines the steps required to implement the momentary pushbutton plug-in [50] and to compile the plug-in on multiple operating systems [51]. A video demonstrating the use of the simulator has been developed, and is intended to be distributed with the application. 7.3.4 Portability The simulator and plug-ins have been compiled and run on multiple operating systems (Figure 25) and have been demonstrated to simulate the benchmark system at sufficient speeds (Figure 26). All manual tests have been carried out on Windows XP, Mac OS X 10.5 and Ubuntu Linux 8.10, and demonstrated to pass. (a) (b) Figure 25: Simulator running on Ubuntu Linux (a) and Mac OS X 10.5 (b). 61 James McGill - 40793625 Embedded Systems Simulator The Scons [52] cross-platform build system can be used to compile the simulator and plug-ins on Mac, Linux and Windows. In addition, Visual Studio and XCode projects have been developed to allow IDE based debugging on Windows and Mac OS X respectively. Percentage of real-time speed achieved by benchmark (2.4 GHz CPU) Mac OS X 10.5 Windows XP Ubuntu Linux 0 50 100 150 200 250 300 350 Figure 26: Comparison of simulator speed on multiple operating systems. 7.4 Discussion The solution presented has been shown to meet and exceed the goals set at the start of the project. The simulation framework is both fast enough to allow real-time simulation of embedded systems (Section 7.2.2), and flexible enough to allow additional components to be developed and distributed independently (Section 5.9). This flexibility has been used to develop all of the components identified as being required for testing and verification (Section 7.3.1). The simulator also provides a simple graphical user interface to allow interaction with the system under simulation (Section 5.8) and which is able to display the current state of each component. The framework developed is also capable of representing interactions between multiple components using multiple signal classes, including open-drain and weak drivers, as demonstrated by the LCD component (Section 6.4). The stability, completeness and correctness of these features have been demonstrated by methodical manual and automated testing. 62 James McGill - 40793625 Embedded Systems Simulator The use of a cross-platform plug-in architecture, and careful choices of support libraries, allow the simulator to be used by developers on multiple operating systems (Section 7.3.4). This is expected to significantly increase the number of developers who are able to use the simulator, and could therefore also be expected to increase the potential pool of plug-in developers. The variation in maximum benchmark simulation speeds observed across the three operating systems tested (Figure 26) is attributed primarily to the optimization capabilities of the different compilers used, as well as the underlying speeds of services provided by the operating systems such as graphics rendering and networking. The difference in simulation speed error between Windows and Mac OS X (Figure 22) is similarly attributed to the services offered by the two operating systems, with Unix-like systems providing a higher resolution timer than Windows. The simulation of the 4MHz Atmel benchmark system (on a 2.4 GHz PC) at 300% of realtime, while maintaining an interactive graphical display, demonstrates that the framework is able to easily exceed the performance goals originally proposed. This result also suggests that the simulator framework should be able to simulate synchronous components of a similar complexity at clock speeds of up to 12MHz. As PC specifications increase, it is expected that the simulator will be able to achieve even higher levels of performance. This speed has been achieved by a combination of a well thought out software architecture, and choice of programming language, and has therefore been achieved without compromising the simulator’s flexibility or accuracy. In addition to fast simulation speeds, the goal of perceptually real-time simulation has been demonstrated as a result of manual testing, and is supported by the measurements presented in 63 James McGill - 40793625 Embedded Systems Simulator Section 7.2.2. The small variations between simulator and wall clock times are unlikely to be noticeable, and further work to decrease this variation is therefore unnecessary. As each implemented AVR instruction is executed at least once by the automatic testing framework, it can be concluded that every instruction implemented can correctly process at least one set of inputs, and that every instruction consumes the correct number of CPU cycles. Given the simplicity of most instructions, it can be assumed that most instructions should correctly handle any input, however further testing would be appropriate. If programs are found which cannot be simulated correctly, the automated testing framework can be used to efficiently isolate and correct the error. The documentation produced, combined with the quality of commenting and use of a consistent programming style throughout the code, are expected to enable this software to be maintained and extended in the future. However, although automatic testing has formed an important component in evaluating the correctness of the overall solution, there has been very little progress made on automatic unit testing of individual elements of the code base. This is primarily a result of the experimental nature of the work, with the architecture of the system changing frequently, and the limited time frame in which it was developed. The lack of unit tests may make extending the simulator framework difficult, and is the primary area in which this thesis fails to excel. Overall, a solution has been presented which is both complete, with respect to the goals outlined in Chapter 4.0, and which has been shown to be correct in all aspects tested. The simulator is expected to be distributed to students enrolled in The University of Queensland’s Introduction to Computer Systems course, demonstrating its usefulness. It is hoped that future 64 James McGill - 40793625 Embedded Systems Simulator work in developing additional components will eventually make the simulator accessible and useful to a much wider range of developers. 7.5 Reflection of project management Time management throughout the project was maintained by constant comparison to the detailed project plan developed as part of the progress report delivered earlier in the project (Appendix G). Throughout the project, progress has consistently been on track with the stated plan, primarily been a result of significant effort and dedication on behalf of the author. This has allowed a solution which meets all of the stated goals to be delivered on time. Based on the results of previous attempts at similar topics and feedback from past thesis students, a large amount of time had been allocated to debugging the implementation of the AT90S8515 plug-in. The development of the automated testing framework, however, significantly reduced the time required to develop a working simulation of this component. As a result, a large amount of additional time was available in which to improve the graphical user interface, and to implement debugging functionality and additional components. This additional time was also used to perform further testing and debugging, resulting in a more stable software package. Owing to concerns regarding the performance of the final solution, a large amount of time was spent micro-optimizing code during the earlier stages of development. Optimising the code base required a great deal of time and effort, often resulting in large changes to the simulator architecture. The results of these optimizations, however, have been largely obscured by later changes to the code base, and are now considered unnecessary. If 65 James McGill - 40793625 Embedded Systems Simulator attempting a similar project, the author would concentrate on achieving speed increases through design and algorithm choices, rather than by code optimization. Overall, the author is extremely satisfied with the quality of the solution developed, and is confident that this has primarily been the result of good planning, successful time management, great personal effort, and a well thought out design. 66 James McGill - 40793625 Embedded Systems Simulator 67 James McGill - 40793625 Embedded Systems Simulator 8.0 Future work Although the simulator developed meets and exceeds all goals, there are still a number of additional features which could be developed to make the program even more useful to embedded systems developers, and which may suggest future areas in which to conduct research. 8.1 Project editor A graphical editor which was able to facilitate adding components to a project, positioning components within the user interface, and connecting pins on components, would be beneficial to users of the simulator. Although projects are assumed to be edited much less frequently than they are run, editing XML by hand is both time consuming and error prone. 8.2 Improved debugging capabilities The debugging functionality currently integrated with the AT90S8515 component is extremely useful; however it lacks features made available by other debuggers. In particular, the debugger is unable to map C variables to memory locations, or to step through C statements. By incorporating the ability to load information contained within the DWARF [53] debugging format, produced as an output of the AVR compilation process, this functionality could be added to future AVR plug-ins. 8.3 Automated testing framework The automatic testing developed thus far is aimed primarily at verifying the accuracy of the simulator software and plug-ins developed, and relies on the graphical representations of components remaining stable. There is scope, therefore, for a framework which can be used to verify that the functionality of an embedded system remains accurate as changes are made to 68 James McGill - 40793625 Embedded Systems Simulator the embedded software, or circuit design, and which does not depend on the graphical state of the system. Such a system could easily be developed by re-using the ability to send events to components to simulate user interaction, and by adding the ability to interrogate the current state of a component. 8.4 Development of additional components It is likely that developers will require a significant base of components to be implemented before they consider using the simulator framework. There is therefore significant work left to be done in implementing additional AVR microcontrollers, microcontrollers from other families, and additional embedded devices. 8.5 Improved separation of simulator state from graphical state In order to ensure that the simulator was able to meet the performance requirements outlined in Chapter 4.0, a decision was made to keep the code used to provide graphical representations of Component objects state integrated with the code used to evaluate that state. It is now clear that a Model-View component architecture which strictly separated state (the Model) from the graphical representation of that state (the View) would be desirable. This would allow views to be re-used among multiple components, and would also allow textonly simulations as a potential speed up. The ability to interrogate a model would also facilitate the development of the automated testing framework outlined in Section 8.3. 69 James McGill - 40793625 Embedded Systems Simulator 9.0 Conclusion The narrow focus on functionality with embedded digital systems has, in the past, made it hard for developers to evaluate the behaviour of a system without access to specialized hardware. This barrier has been partially removed by the development of PC based simulators, which employ simulation algorithms to provide a model of the state of the digital system over time. An examination of the existing offerings in this field identified that there did not currently exist an offering which was both affordable by novice developers and students, and which was flexible and extensible enough to allow any digital embedded system to be simulated. A proposal was therefore put forward by James McGill and Dr. Peter Sutton to develop a fast, extensible simulator for embedded systems. The result of this proposal, presented in this document, is a cross-platform software framework and application for the simulation of digital embedded systems. The software developed uses an extensible software architecture to allow simulated versions of embedded devices to be developed and distributed independently. A discrete event simulation algorithm is used to provide an accurate model of the system’s state, and provides a framework to allow components to interact via simulated electrical connections. Events within the simulation algorithm are partitioned into multiple event sets, providing a speed increase by allowing synchronous events to be represented efficiently. The simulator was shown to be able to utilise real-time simulation speeds, when possible, and a graphical user interface, to allow users to interact with a simulated system in a way that is consistent with use of a real device. In order to demonstrate the functionality of the simulator, a number of simulated components have been developed as plug-ins. In addition to an 8-bit AT90S8515 microcontroller, character LCD, speaker and LED matrix, a component was developed to interface the RS232 70 James McGill - 40793625 Embedded Systems Simulator communication protocol to a TCP/IP socket, demonstrating the ability for the simulator to interact with both users and external systems. Systematic manual and automatic testing has shown that these plug-ins are able to provide accurate simulations of the real digital components which they represent. To provide a more accurate measure of the microcontroller’s correctness, an automated testing framework was developed which uses comparisons with data extract from a physical or simulated device to isolate and identify implementation errors. The black box nature of the framework also made it particularly valuable in identifying incorrect assumptions about the devices expected behaviour. This framework was used to refine the implementation of the plug-in, and to demonstrate that the basic functionality of the full AT90S8515 instruction set implemented is correct. As an additional measure of verification, a submission to the University of Queensland Introduction to Computer Systems subject was chosen for use as a performance benchmark. This benchmark was simulated accurately, and at speeds that indicate that real time simulation of a 12 MHz microcontroller in a simple digital system should be achievable on a 2.4 GHz PC. When simulation speeds were constrained to real-time, the magnitude of the error between simulator time and real-time was observed to be 2ms on average, which is consistent with manual observations and with the goal of achieving real-time simulation. These results were found to be relatively consistent on Windows XP, Linux and Mac OS X, although the maximum achievable benchmark simulation speed varied between 220% and 300% of 4MHz. A critical examination of these results in the context of the goals of the project revealed that the end results meets and exceeds the goals of performance and functionality originally proposed. The submission is also complete with respect to the proposed documentation, level of maintainability, and the desired software architecture. Unfortunately, the code written thus 71 James McGill - 40793625 Embedded Systems Simulator far lacks unit testing, primarily as a result of the short time-frame in which it was developed. This may impact the ability for additional developers to stably extend the core offering. A number of areas have also been identified in which the simulator could be improved, suggesting possible future avenues for research into this area. Overall, a solution has been presented which is both complete, with respect to the goals outlined, and which is expected to be useful to those interested in the development of embedded systems. 72 James McGill - 40793625 Embedded Systems Simulator List of References [1] P. Koopman, "Undergraduate embedded system education at Carnegie Mellon," ACM Transactions on Embedded Computing Systems, vol. 4, no. 3, pp. 500-528, Aug. 2005. [2] J. A. Fisher, P. Farabos, and C. Young, Embedded Computing; A VLIW approach to architecture, compilers and tools. San Fransisco, CA: Elsevier, 2005. [3] Atmel. (2008, Jul.) AVR Studio 4. [NotOnline]. http://www.atmel.com/dyn/Products/tools_card.asp?tool_id=2725 [4] Labcenter Electronics. (2008, Sep.) Proteus VSM. [NotOnline]. http://www.labcenter.co.uk/products/vsm_overview.cfm [5] Oshon Software. (2008, Aug.) Avr Simulator IDE. [NotOnline]. http://www.oshonsoft.com/avr.html [6] T. J. Schriber and D. T. Brunner, "Inside simulation software: inside discrete-event simulation software: how it works and why it matters," in Proceedings of the 33nd conference on Winter simulation, Alrington, 2001, pp. 158-168. [7] P. M. Maurer, "The Inversion Algorithm for digital simulation," in Proceedings of the 1994 IEEE/ACM international conference on Computer-aided design, San Jose, 1994, pp. 258-261. [8] B. Franke, "Fast cycle-approximate instruction set simulation," in Proceedings of the 11th international workshop on Software & compilers for embedded systems, Munich, 2008, pp. 69-78. [9] S. A. Szygenda and A. A. Lekkos, "Integrated techniques for functional and gate-level digital logic simulation," in Proceedings of the 10th workshop on Design automation, Piscataway, 1973, pp. 159-172. [10] L. Gauthier and A. Jerraya, "Cycle-true simulation of the S10 microcontroller including the core and the peripherals.," in Proceedings of the 11th IEEE International Workshop on Rapid System Prototyping, Washington, 2000, pp. 60-65. [11] H. Muhr and R. Holler, "Accelerating RTL Simulation by Several Orders of Magnitude Using Clock Suppression," in Embedded Computer Systems: Architectures, Modeling and Simulation, 2006. IC-SAMOS 2006. International, 2006, pp. 123-128. [12] L. Eeckhout, S. Nussubaum, and K. De Bosschere, "Statistical simulation: adding efficiency to the computer designer's toolbox," IEEE Micro, vol. 23, no. 5, pp. 26-38, Sep. 2003. [13] D. Jones, "An empirical comparison of priority-queue and event-set implementations," Communications of the ACM, vol. 29, no. 4, pp. 300-311, Apr. 1986. 73 James McGill - 40793625 Embedded Systems Simulator [14] J. Comfort, "The simulation of a microprocessor based event set processor," in Proceedings of the 14th annual symposium on Simulation, Tampa, 1981, pp. 17-33. [15] R. Brown, "Calendar queues: a fast 0(1) priority queue implementation for the simulation event set problem," Communications of the ACM, vol. 31, no. 10, pp. 12201227, Oct. 1988. [16] R. Goh and I. Thng, "MLIST: An efficient pending event set structure for discrete event simulation.," International Journal of Simulation, vol. 4, no. 5-6, pp. 66-77, Jun. 2004. [17] P. Phillips and G. Phillips, "No Source Code? No Problem," ACM Queue, vol. 1, no. 6, pp. 50-57, Sep. 2003. [18] W. Vogels, "HPC.NET - are CLI-based Virtual Machines Suitable for High Performance Computing?," in Proceedings of the 2003 ACM/IEEE conference on Supercomputing, Washington, 2003, p. 36. [19] R. A. Kilgore, "Object-oriented simulation with SML and Silk in Java and .Net," in Proceedings of the 35th conference on Winter simulation: driving innovation, New Orleans, 2003, pp. 218-224. [20] E. W. Thompson and N. Billawala, "The software engineering technique of data hiding as applied to multi-level model implementation of logical devices in digital simulation," in Proceedings of the 12th conference on Design automation, Piscataway, 1975, pp. 192-201. [21] Atmel. (2008, Sep.) AT90S8515. [NotOnline]. http://www.atmel.com/dyn/resources/prod_documents/doc0841.pdf [22] University of Queensland. (2008, Sep.) AVR Project Board Schematic. [NotOnline]. http://www.itee.uq.edu.au/~csse1000/pracs/Atmel_AVR_Resources/AVR_Project_Boa rd.pdf [23] H. Freeman, "Software testing," Instrumentation & Measurement Magazine, IEEE, vol. 5, no. 3, pp. 48-50, Sep. 2002. [24] S. McConnell, Code Complete, 2nd ed., D. Musgrave, Ed. Redmond, America: Microsoft Press, 2004. [25] P. Goodliffe, Code Craft, 1st ed., E. Campbell, Ed. San Fransisco, America: No Starch Press, 2007. [26] N. Reynolds, "Embedded Systems Simulator," University of Queensland Bachelor of Engineering Honours Thesis, 2007. [27] J. Kehl, "Embedded System Simulator," University of Queensland Bachelor of Engineering Honours Thesis , 2004. 74 James McGill - 40793625 Embedded Systems Simulator [28] D. Nixon, "Embedded System Simulator," University of Queensland Bachelor of Engineering Honours Thesis, 2004. [29] Atmel. (2006, Jul.) AVR JTAG ICE MKII. [NotOnline]. http://www.atmel.com/dyn/Products/tools_card.asp?tool_id=3353 [30] Feersum Technology. (2008, Sep.) miSIim DE. [NotOnline]. http://www.feertech.com/misim/ [31] Dallas Semiconductor. (2008, Aug.) DS1821 Programmable Digital Thermostat and Thermometer. [NotOnline]. http://datasheets.maxim-ic.com/en/ds/DS1821.pdf [32] Dallas Semiconductor. (2001, Mar.) Application Note 83: Fundamentals of RS-232 Serial Communications. [NotOnline]. http://www.maximic.com/appnotes.cfm/an_pk/83 [33] The University of Queensland. (2007, Oct.) LED Display Board . [NotOnline]. http://www.itee.uq.edu.au/~csse1000/assessment/project/LED_Display_Board.html [34] Cairo Graphics. (2009, Apr.) Cairo Graphics. [NotOnline]. http://cairographics.org/ [35] Gnome. (2009, Jun.) GDK Reference Manual. [NotOnline]. http://library.gnome.org/devel/gdk/ [36] Gnome. (2009, Jun.) Graphical Interfaces. [NotOnline]. http://library.gnome.org/devel/platform-overview/stable/graphics.html.en [37] E. Gamma, R. Helm, R. Johnson, and J. Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software, 1st ed., B. Kernighan, Ed. Massachusetts, United States of America: Addison-Wesley, 2007. [38] GTK. (2009, Apr.) gtkmm: The C++ Interfaces for GTK and Gnome. [NotOnline]. http://www.gtkmm.org/ [39] wxWidgets. (2009, Jun.) wxWidgets. [NotOnline]. http://www.wxwidgets.org/ [40] Nokia. (2009, Jun.) Qt. [NotOnline]. http://www.qtsoftware.com/products/ [41] G. Sayfan. (2007, Nov.) Dr Dobb's Portal. [NotOnline]. http://www.ddj.com/cpp/204202899 [42] World Wide Web Consortium. (2009, Jun.) XML. [NotOnline]. http://www.w3.org/XML/ [43] Internet Engineering Task Force. (2009, Jun.) RFC 4627. [NotOnline]. http://www.ietf.org/rfc/rfc4627.txt?number=4627 [44] C. C. Evans. (2009, Jun.) The Official YAML Website. [NotOnline]. http://yaml.org 75 James McGill - 40793625 Embedded Systems Simulator [45] L. Thompson. (2009, Mar.) TinyXML Library. [NotOnline]. http://www.grinninglizard.com/tinyxml/ [46] Atmel. (2009, Apr.) AVR 8-bit Instruction Set. [NotOnline]. www.atmel.com/dyn/resources/prod_documents/doc0856.pdf [47] A. Holovaty and J. Kaplan-Moss, The Definitive Guide to Django, 1st ed., J. Gilmore, Ed. New York, United States of America: Apress, 2008. [48] Port Media. (2009, Apr.) Port Media APIs. [NotOnline]. http://portmedia.sourceforge.net/ [49] J. Bennett. (2009, Jun.) AutoIt Scripting Language. [NotOnline]. http://www.autoitscript.com/autoit3/ [50] J. McGill. (2009, Apr.) ESS Component Tutorial. [NotOnline]. http://code.google.com/p/plex-svn/wiki/ComponentTutorial [51] J. McGill. (2009, Apr.) ESS Compilation Tutorial. [NotOnline]. http://code.google.com/p/plex-svn/wiki/ComponentTutorial [52] Scons. (2009, Apr.) Scons build system. [NotOnline]. http://www.scons.org/ [53] SGI. (2008, Sep.) libdwarf Homepage. [NotOnline]. http://reality.sgiweb.org/davea/dwarf.html 76 James McGill - 40793625 Embedded Systems Simulator Appendix A: XML Schema for simulation project files <xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'> <xsd:element name='name' type='xsd:string'> </xsd:element> <xsd:element name='author' type='xsd:string'> </xsd:element> <xsd:element name='property'> <xsd:complexType> <xsd:attribute name='key' type='xsd:string' use='required'/> <xsd:attribute name='value' type='xsd:string' use='required'/> </xsd:complexType> </xsd:element> <xsd:element name='component'> <xsd:complexType> <xsd:sequence minOccurs='0'> <xsd:element ref='property'/> </xsd:sequence> <xsd:attribute name='name' type='xsd:string' use='required'/> <xsd:attribute name='type' type='xsd:string' use='required'/> <xsd:attribute name='x' type='xsd:integer' use='required'/> <xsd:attribute name='y' type='xsd:integer' use='required'/> </xsd:complexType> </xsd:element> <xsd:element name='components'> <xsd:complexType> <xsd:sequence minOccurs='1' maxOccurs='unbounded'> <xsd:element ref='component'/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name='pin'> <xsd:complexType> <xsd:attribute name='component' type='xsd:string' use='required'/> <xsd:attribute name='pin' type='xsd:string' use='required'/> </xsd:complexType> </xsd:element> <xsd:element name='connection'> <xsd:complexType> <xsd:sequence minOccurs='2' maxOccurs='unbounded'> <xsd:element ref='pin'/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name='connections'> <xsd:complexType> <xsd:sequence minOccurs='1' maxOccurs='unbounded'> <xsd:element ref='connection'/> </xsd:sequence> </xsd:complexType> </xsd:element> 77 James McGill - 40793625 Embedded Systems Simulator <xsd:element name='project'> <xsd:complexType> <xsd:sequence> <xsd:element ref='name'/> <xsd:element ref='author'/> <xsd:element ref='components'/> <xsd:element ref='connections'/> <xsd:element ref='layout'/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema> 78 James McGill - 40793625 Embedded Systems Simulator Appendix B: Django templates for AvrInstruction and AvrMemory skeleton classes #ifndef _AVR_{{ mnemonic }}_ #define _AVR_{{ mnemonic }}_ #include "common/types.h" #include "common/binary-utils.h" #include "atmel/avr-instruction.h" class AvrCore; class AvrMemory; class {{ class }} : public AvrInstruction { public: {{ class }}(AvrCore *core) : AvrInstruction(core) {} /// Run the instruction. void execute(); /// Initialize the instruction using the actual FLASH memory value. void init(uint32 instruction); /// Assembly representatin of the instruction. const string assemblyString() const; /// Description of the instruction. const string description() const; /// A 32 bit mask which can be used to isolate the instruction identifier. uint32 mask_32() const; /// A 32 bit representation of the instruction. uint32 instruction_value_32() const; /// Update the status register. unsigned int updateStatusRegister(); // The size of the instruction in bytes. unsigned int size(); // Factory method to create an instance of this type. AvrInstruction *create(AvrCore *core); private: {% if destination_register %} // Destination register. AvrMemory *destination_register_; // Constant register offset, added to the register value. static const signed int destination_register_offset_ = {{ destination_register_offset }}; // The address of the destination register. int destination_register_index_; // The bit positions in the instruction in which the destination register // is stored. static const int destination_register_bit_positions_[{{ destination_register_length }}]; 79 James McGill - 40793625 Embedded Systems Simulator {% endif %} {% if 16_bit_register %} // Destination register low - used for 16 bit operations. AvrMemory *destination_register_low_; // Destination register high - used for 16 bit operations. AvrMemory *destination_register_high_; // The address of the low byte of the 16 bit register. int destination_register_low_index_; // The address of the high byte of the 16 bit register. int destination_register_high_index_; // Constant register offset, added to the register value. static const signed int wide_register_offset_ = {{ 16_bit_register_offset }}; // The bit positions in the instruction in which the 16 bit register to use // is identified. static const int wide_register_bit_positions_[{{ 16_bit_register_length }}]; {% endif %} {% if source_register %} // Source register. AvrMemory *source_register_; // Constant register offset, added to the register value. static const signed int source_register_offset_ = {{ source_register_offset }}; // The address of the source register. int source_register_index_; // The bit positions in the instruction in which the source register is // stored. static const int source_register_bit_positions_[{{ source_register_length }}]; {% endif %} {% if io_register %} // IO register. AvrMemory *io_register_; // The address of the IO register. int io_register_index_; // The bit positions in the instruction in which the destination register // is stored. static const int io_register_bit_positions_[{{ io_register_length }}]; {% endif %} {% if constant_data %} // Constant data from the instruction. unsigned int constant_data_; // The bit positions in the instruction in which the constant data is stored. 80 James McGill - 40793625 Embedded Systems Simulator static const int constant_data_bit_positions_[{{ constant_data_length }}]; {% endif %} {% if constant_address %} // Constant relative address. signed int constant_address_; // Maximum value of the constant address, used to convert to an n-bit signed value. static const signed int constant_address_max_ = {{ constant_address_max }}; // Constant address offset, added to the address value. static const signed int constant_address_offset_ = {{ constant_address_offset }}; // The bit positions in the instruction in which the constant address is // stored. Static const int constant_address_bit_positions_[{{ constant_address_length }}]; {% endif %} {% if bit_number %} // Bit number in IO or Status register. unsigned int bit_number_; // The bit positions in the instruction in which the bit number is stored. static const int bit_number_bit_positions_[{{ bit_number_length }}]; {% endif %} {% if displacement %} // Displacement for direct addressing. unsigned int displacement_; // The bit positions in the instruction in which the displacement is stored. static const int displacement_bit_positions_[{{ displacement_length }}]; {% endif %} }; #endif Django template to generate an Instruction header file. 81 James McGill - 40793625 Embedded Systems Simulator /** * Avr {{ mnemonic }} Instruction * {{ description }} * * Operation: * {{ operation }} * * Opcode: * {{ opcode }} * * Status Register effects: * {{ sreg_flags }} * * Clock cycles: * {{ clock_cycles }} * * Implementation status: * Incomplete. */ #include #include #include #include #include #include "{{ mnemonic|lower }}.h" "atmel/avr-core.h" "atmel/avr-memory.h" "common/binary-utils.h" <exception> <sstream> {# Decleration of static variables #} {% if destination_register %} const int {{ class }}::destination_register_bit_positions_[{{ destination_register_length }}] = { {{ destination_register_bit_positions_string }} }; {% endif %} {% if 16_bit_register %} const int {{ class }}::wide_register_bit_positions_[{{ 16_bit_register_length }}]= { {{ 16_bit_register_bit_positions_string }} }; {% endif %} {% if source_register %} const int {{ class }}::source_register_bit_positions_[{{ source_register_length }}] = { {{ source_register_bit_positions_string }} }; {% endif %} {% if constant_data %} const int {{ class }}::constant_data_bit_positions_[{{ constant_data_length }}] = { {{ constant_data_bit_positions_string }} }; {% endif %} {% if constant_address %} const int {{ class }}::constant_address_bit_positions_[{{ constant_address_length }}] = { {{ constant_address_bit_positions_string }} }; 82 James McGill - 40793625 Embedded Systems Simulator {% endif %} {% if io_register %} const int {{ class }}::io_register_bit_positions_[{{ io_register_length }}] = { {{ io_register_bit_positions_string }} }; {% endif %} {% if bit_number %} const int {{ class }}::bit_number_bit_positions_[{{ bit_number_length }}] = { {{ bit_number_bit_positions_string }} }; {% endif %} {% if displacement %} const int {{ class }}::displacement_bit_positions_[ {{displacement_length }}] = { {{ displacement_bit_positions_string }} }; {% endif %} {# Functions #} void {{ class }}::init(uint32 instruction) { {% if destination_register %} // Extract the destination register index from the instruction, and get a // pointer to that register. destination_register_index_ = BinaryUtils::extractSparseValue( instruction, destination_register_bit_positions_); destination_register_index_ += destination_register_offset_; destination_register_ = avr_core_->getWorkingRegister( destination_register_index_); {% endif %} {% if source_register %} // Extract the source register index from the instruction, and get a // pointer to that register. source_register_index_ = BinaryUtils::extractSparseValue(instruction, source_register_bit_positions_); source_register_index_ += source_register_offset_; source_register_ = avr_core_->getWorkingRegister(source_register_index_); {% endif %} {% if io_register %} // Extract the IO register index from the instruction, and get a // pointer to that register. io_register_index_ = BinaryUtils::extractSparseValue( instruction, io_register_bit_positions_); io_register_ = avr_core_->memoryByAddress(io_register_index_); {% endif %} {% if constant_data %} // Extract the constant value from the instruction. constant_data_ = BinaryUtils::extractSparseValue(instruction, constant_data_bit_positions_); {% endif %} 83 James McGill - 40793625 Embedded Systems Simulator {% if constant_address %} // Extract the constant address (or relative address) from the instruction. constant_address_ = static_cast<signed int>(BinaryUtils::extractSparseValue( instruction, constant_address_bit_positions_)); // Wrap around for signed values. if (constant_address_ > constant_address_max_) { constant_address_ = (constant_address_ - (constant_address_max_ + 1) + constant_address_offset_); } // TODO: This might need to be resolved to a memory address. {% endif %} {% if bit_number %} // Extract the bit number from the instruction. bit_number_ = BinaryUtils::extractSparseValue(instruction, bit_number_bit_positions_); {% endif %} {% if displacement %} // Extract the address displacement from the instruction. displacement_ = BinaryUtils::extractSparseValue(instruction, displacement_bit_positions_); {% endif %} {% if 16_bit_register %} // 16 bit registers must be handled as a special case as they do not map // nicely. int wide_register_index = BinaryUtils::extractSparseValue( instruction, wide_register_bit_positions_); // 16 bit registers increment in lots of 2, so double the extracted value. wide_register_index = (wide_register_index * 2); destination_register_low_index_ = wide_register_index + wide_register_offset_; destination_register_high_index_ = destination_register_low_index_ + 1; destination_register_low_ = avr_core_->getWorkingRegister( destination_register_low_index_); destination_register_high_ = avr_core_->getWorkingRegister( destination_register_low_index_); {% endif %} } void {{ class }}::execute() { throw std::runtime_error("Instruction {{ mnemonic }} is not implemented"); } const string {{ class }}::assemblyString() const { std::ostringstream output; output << "{{ mnemonic }}" {% for operand in display_operands %} {% ifequal forloop.counter0 0 %}<< " " {% else %}<< ", " {% endifequal %}<< hex << "0x" << {{ operand }}{% endfor %}; 84 James McGill - 40793625 Embedded Systems Simulator return output.str(); } const string {{ class }}::description() const { return "{{ mnemonic }} {{ operands }} : {{ description }}"; } uint32 {{ class }}::mask_32() const { return {{ masmailk_32 }}; } uint32 {{ class }}::instruction_value_32() const { return {{ instruction_32 }}; } unsigned int {{ class }}::updateStatusRegister() { throw std::runtime_error("Instruction {{ mnemonic }} SREG effects not implemented"); } unsigned int {{ class }}::size() { return {{ size }}; } AvrInstruction *{{ class }}::create(AvrCore *core) { return new {{ class }}(core); } Django template to generate an Instruction implementation (cpp) file. 85 James McGill - 40793625 Embedded Systems Simulator /** * @author James McGill (jmcgill@plexer.net) * * @fileoverview An AvrMemory object is used to encapculate the special * functionality and metadata associated with a register in an AVR * microcontroller. * * This file is initially automatically generated from the AVR Part * Description XML file and is later edited by hand to implement the * registers functionality. */ #include "common/log.h" #include "common/types.h" #include "AtmelCore/avr-memory.h" class AvrCore; class {{ class }} : public AvrMemory { public: // An instance of the core is passed in during construction to allow O(1) // access. {{ class }}(AvrCore *core) : AvrMemory(core) {} // Initiailize the memory object, including finding links to other // registers. bool init(); // Return the shortname name of the register. const string &name(); // Return a short description of the registers purpose. const string &description(); // Return the IO memory location (offset into SRAM). int io_memory_location(); // Return the register memory location. int register_memory_location(); // Return a mask which can be used to isolate which bits can be read // from. int read_mask(); // Return a mask which can be used to isolate which bits can be written // to. int write_mask(); // Return the initial state which the register should be initialized to. int initial_value(); // Get the shorthand name for a bit, based on the index (from 0). const string bit_nameByIndex(int index); // If the register needs to do something special when read from or // written to // then uncomment the following block of code. /* // Handler for reading data from a byte of memory. unsigned char read(); 86 James McGill - 40793625 Embedded Systems Simulator // Handler for writing data to a byte of memory. void write(unsigned char data); */ private: // Shorthand name for each bit in this register, as defined by the Atmel // datasheets. const static string bit_names_[8]; // Each register has two locations - one in IO space and one in register // space. Each maps to the same real memory location. const static int io_memory_location_ = {{ io_addr }}; const static int register_memory_location_ = {{ mem_addr }}; // Shorthand name for the register, as recorded in the datasheet. const static string name_; // A simple description of the register. const static string description_; // Mask used to prevent data being written to read only bits. const static int write_mask_ = {{ write_mask }}; // Mask used to prevent data being read from write only bits. const static int read_mask_ = {{ read_mask }}; // The value of this register upon initialization / reset. const static int initial_value_ = {{ initial_value }}; {% if partner_register %} // The name of the partner register. const static string partner_register_name_; // The IO memory address of the partner register. const static int partner_register_io_address_ = {{ partner_io_address }}; // Pointer to the register paired with register. AvrMemory *partner_register_; {% endif %} }; this one to make Django template to generate an AvrMemory header (h) file. 87 a 16 bit James McGill - 40793625 Embedded Systems Simulator /** * @author James McGill (jmcgill@plexer.net) */ #include "{{ name|lower }}.h" #include "AtmelCore/avr-memory.h" #include "AtmelCore/avr-core.h" /* unsigned char {{ class }}::read() { } Void {{ class }}::write(unsigned char data) { } */ bool {{ class }}::init() { {% if partner_register %} partner_register_ = core_->memoryByAddress(partner_register_io_address_); {% endif %} return true; } const string &{{ class }}::name() { return name_; } const string &{{ class }}::description() { return description_; } int {{ class }}::io_memory_location() { return io_memory_location_; } int {{ class }}::register_memory_location() { return register_memory_location_; } int {{ class }}::read_mask() { return read_mask_; } int {{ class }}::write_mask() { return write_mask_; } int {{ class }}::initial_value() { return initial_value_; } const string {{ class }}::bit_nameByIndex(int index) { return bit_names_[index]; } const string {{ class }}::bit_names_[8] = { {% for bit in bits %} "{{ bit.name }}"{% endfor %} }; const string {{ class }}::name_ = "{{ name }}"; 88 James McGill - 40793625 Embedded Systems Simulator const string {{ class }}::description_ = "{{ description }}"; {% if partner_register %} const string partner_register_name_ = "{{ partner_register_name }}"; {% endif %} Django template to generate an AvrMemory implementation (cpp) file. 89 James McGill - 40793625 Embedded Systems Simulator Appendix C: Manual testing plan ESS MANUAL TESTING PLAN ID: 1 Purpose: Verify that CSSE1000 Prac 4 simulates correctly. Project description: Two’s complement negation of 8 switch inputs is output to 8 LEDs. Simulation project: projects/pracs/prac4.smx Expected appearance: Testing procedure: NOTE: LEDs and Switches are numbered from 1 to 8, left to right. Passed? Action Expected output Start simulation 1. All LEDs are off (outline only) 2. All Switches are off (outline only) Click switches 1, 3 and 5 with the left mouse button. 1. Clicked switches are filled. 2. LEDs 1, 2, 4, 6, 7, 8 turn on. Click the same switches with the left mouse button. 1. Clicked switch turns off. 2. All LEDs turn off. 90 James McGill - 40793625 Embedded Systems Simulator Appendix D: Summary of manual tests Test name Test purpose Test summary Key aspects tested Prac 4 Verify that CSSE1000 Prac 4 Output the two's complement of 8 switches LED, Switch, AVR PORT, PIN and DDR simulates correctly. to 8 LEDs. Registers. Verify that CSSE1000 Prac Output the two's complement of 8 switches LED, Switch, AVR PORT, PIN and DDR 5-1 simulates correctly. to 8 LEDs. Registers. Verify that CSSE1000 Prac Output the index of the active switch to a Seven Segment, Switch, AVR PORT, PIN 5-2 simulates correctly. seven segment display. and DDR Registers, Conditional logic Verify that CSSE1000 Prac Output the index of the active switch to a Seven Segment, Switch, AVR PORT, PIN 5-3 simulates correctly. seven segment display. and DDR Registers, Conditional logic Verify that CSSE1000 Prac Output the two’s complement of 8 switches LED, Switch, AVR PORT, PIN and DDR 6-1 simulates correctly. to 8 LEDs. Registers. C Code. Verify that CSSE1000 Prac Output the index of the active switch to a Seven Segment, Switch, AVR PORT, PIN 6-2 simulates correctly. seven segment display. and DDR Registers. C Code. Conditional Prac 5-1 Prac 5-2 Prac 5-3 Prac 6-1 Prac 6-2 logic. 91 James McGill - 40793625 Embedded Systems Simulator Test name Test purpose Test summary Key aspects tested Prac 6-3 Verify that CSSE1000 Prac Output the index of the active switch to a Seven Segment, Switch, AVR PORT, PIN 6-3 simulates correctly. seven segment display. and DDR Registers. C Code. Conditional logic. Prac 7-1 Prac 7-2 Prac 7-3 Prac 8-1 Verify that CSSE1000 Prac Drive a speaker at 1KHz with a software Speaker, Timers/Counter 1, Simulator 7-1 simulates correctly. timer. timestamps. Verify that CSSE1000 Prac Drive a speaker at 1KHz using the 16 bit Speaker, Timer/Counter 1, CTC and PWM. 7-2 simulates correctly. AT90S8515 Timer/Counter 1 in CTC mode. Verify that CSSE1000 Prac Drive a speaker at 1KHz using the 16 bit Speaker, Timer/Counter 1,CTC and PWM. 7-3 simulates correctly. AT90S8515 Timer/Counter 1 in CTC mode. C Code. Verify that CSSE1000 Prac Drive a speaker at 1KHz using the 16 bit Speaker, Timer/Counter 1, PWM and CTC, 8-1 simulates correctly. AT90S8515 Timer/Counter 1 in CTC Mode. External interrupts. Mute speaker in response to an edge triggered interrupt. Prac 8-2 Verify that CSSE1000 Prac Drive a speaker at 1KHz using the 16 bit Speaker, Timer/Counter 1, Timer/Counter 0, 8-2 simulates correctly. AT90S8515 Timer/Counter 1 in CTC Mode PWM and CTC, External interrupts. for at most 1.5 seconds. Restart the speaker in response to an edge triggered interrupt. 92 James McGill - 40793625 Embedded Systems Simulator Test name Test purpose Test summary Key aspects tested Prac 8-3 Verify that CSSE1000 Prac USART echo with digits 1 - 9 translated to USART, RS232 to TCP/IP, Baud rate 8-3 simulates correctly. words (one – nine). detection, USART Interrupts Verify that pin values are 3 flip flops are chained together and all Flip flop component, simulator timestamps, buffered when components clocked at 1Hz. simulator stability, real-time simulation. Verify that EEPROM can be Phrase is read from EEPROM, displayed on USART, EEPROM read from and written to. USART, encoded using an inverting code, T Flip Flops are updated simultaneously. EEPROM and written back to EEPROM. Momentary Verify that asynchronous A pushbutton is released exactly two Real time simulation of asynchronous switch. components can be simulated seconds after it is pressed. components. Timer/Counter 0, Seven Segment component in real-time. Seven Verify that the seven segment Cycle through all 16 digits at 1 Hz using the Segment component works. AT90S8515 Timer/Counter 0. Verify that the LCD Display two lines of text and scroll them off LCD, real-time simulation, Timer/Counter 0, component works the screen. Contains one (purposeful) timing Error reporting. Display LCD error. 93 James McGill - 40793625 Embedded Systems Simulator Test name Test purpose Test summary Key aspects tested Tetris Verify that Tetris runs Run a feature-rich Tetris game submission USART, Interrupts, Speaker, correctly and at the correct from a past student, selected as the system Timers/Counters, Performance, C Code. speed. benchmark. Verify that Snake runs Run a feature-rich Snake game submission USART, Interrupts, Speaker, Performance, C correctly and at the correct of my own. Code. Verify that Asteroids runs Run a feature-rich Asteroids game USART, Interrupts, Speaker, correctly and at the correct submission from a past student. Timers/Counters, Performance, C Code. Snake speed. Asteroids speed. 94 James McGill - 40793625 Embedded Systems Simulator Appendix E: Automated testing command language description (string description) The description instruction appends a string to the textual description of the tests purpose. steps (int number_of_steps) The steps instruction sets the number of execution steps to test. The results of any previous calls to the function are overwritten. stepsize (int step_size) The stepsize instruction sets the number of steps to execute between performing a comparison. This allows larger tests to be executed quickly, with only limited impact on accuracy, as most errors are likely to persist for several execution steps or eventually lead to following an incorrect code branch. The results of any previous calls to the function are overwritten. repair (int step, string memory_type, int address, int new_value) The repair instruction replaces the expected value of an address at a given step. This is used to correct errors in the output of AVR Studio’s software simulations, which are known to handle 16 bit registers incorrectly. ignore (int start_step, int end_step, string memory_type, int start_address, int end_address) The ignore instruction set an address range which will not be tested during a range of execution steps. This facilitates testing partial implementations of the microcontroller by allowing unimplemented address ranges to be ignored. 95 James McGill - 40793625 Embedded Systems Simulator Appendix F: Python script to save simulator state from AVR Studio # # # # # # # # # # # # @author James McGill (jmcgill@plexer.net) Extract a golden file from an AVR Studio project using the debugger. Dependancies: AutoIt COM Library (http://www.autoitscript.com/AutoIt) PyWin32 (http://python.net/crew/mhammond/win32/Downloads.htm) Steps for use: 1. Load the project in AVR Studio 2. Start debugging, and enter the disassembly view. 3. Reset the simulator, and clear the state of SRAM. 4. Start this script. from win32com.client import Dispatch import time import os memory_types = ("Data", "I", "Reg") def saveAllMemories(Auto, path, step): global memory_types for memory_type in memory_types: # Keep sending key press until window opens, as sometimes it gets missed. try_again = 0 while try_again is 0: Auto.Send("!d") Auto.Send("u") # Will return 0 if it times out. try_again = Auto.WinWaitActive("Up", "", 1) # Open the save memory dialog box Auto.ControlClick("Up", "", "[ID:1103]") Auto.ControlSend("Up", "", "[ID:1103]", memory_type + "{ENTER}") Auto.ControlClick("Up", "", "[ID:1123]") # Enter the path to save the file to while len(Auto.ControlGetText("Up", "", "[ID:1123]")) is not 0: Auto.ControlSend("Up", "", "[ID:1123]", "{END}{BACKSPACE}") Auto.ControlSend("Up", "", "[ID:1123]", os.path.join(path, memory_type, str(step) + ".txt")) # Save the file Auto.ControlClick("Up", "", "[ID:1186]") Auto.WinClose("Up") def createBaseDirectories_(path): global memory_types for memory_type in memory_types: os.mkdir(os.path.join(path, memory_type)) def main(path, num_steps): print 'Running main function' Auto = Dispatch("AutoItX3.Control") Auto.WinActivate("AVR Studio") Auto.WinWaitActive("AVR Studio") createBaseDirectories_(path) 96 James McGill - 40793625 Embedded Systems Simulator for i in range(0, num_steps): print "Running step", i, "of", num_steps saveAllMemories(Auto, path, i) Auto.Send("{F11}") if __name__=='__main__': main("c:\\project001", 20000) 97 James McGill - 40793625 Embedded Systems Simulator Appendix G: Project progress plan 98 James McGill - 40793625 Embedded Systems Simulator Progress plan (Gantt chart) for Semester 1, 2009 99 James McGill - 40793625 Embedded Systems Simulator Progress plan (Gantt chart) for Semester 2, 2009 100