Simics User Guide for Linux

September 1, 2017 | Author: lohit24 | Category: 64 Bit Computing, Command Line Interface, Operating System, Booting, Linux
Share Embed Donate


Short Description

Processor simulation Tool...

Description

virtutech

Simics User Guide for Unix Simics 1.6.1

[email protected], www.simics.net

February 18, 2003

(c) Copyright 1998-2003 Virtutech AB. Norrtullsgatan 15, SE-113 27 STOCKHOLM, Sweden TRADEMARKS Virtutech, the Virtutech logo, and Simics are trademarks or registered trademarks of Virtutech AB or Virtutech, Inc. in the United States and or other countries. THIS PUBLICATION IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. THIS PUBLICATION COULD INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS. CHANGES ARE PERIODICALLY ADDED TO THE INFORMATION HEREIN; THESE CHANGES WILL BE INCORPORATED IN NEW EDITIONS OF THE PUBLICATION. VIRTUTECH MAY MAKE IMPROVEMENTS AND/OR CHANGES IN THE PRODUCT(S) AND/OR THE PROGRAM(S) DESCRIBED IN THIS PUBLICATION AT ANY TIME.

Contents I

Starting with Simics

1

Introduction 1.1 Hosts and Targets . . . . . . . . . 1.2 Simics Targets - Fully Supported 1.2.1 Simics/SunFire . . . . . . 1.2.2 Simics/Serengeti . . . . . 1.2.3 Simics/x86 . . . . . . . . . 1.2.4 Simics/x86-64 . . . . . . . 1.3 Simics Targets - Limited Support 1.3.1 Simics/Alpha . . . . . . . 1.3.2 Simics/PPC . . . . . . . . 1.3.3 Simics/IA-64 . . . . . . . 1.3.4 Simics/ARM . . . . . . . 1.3.5 Simics/MIPS . . . . . . . 1.4 This Document . . . . . . . . . . 1.5 Other Documentation . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

11 12 12 13 13 13 13 13 13 14 14 14 14 14 15

Installation 2.1 Licenses . . . . . . . . . 2.2 Flexlm Floating Licenses 2.3 Multi-User Environment 2.4 .tf Encoded Files . . . . . 2.5 Getting Disk Images . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

17 17 17 19 20 20

First Steps 3.1 Downloading FirstSteps Disk Image . . . . . . . . . . 3.2 Booting . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3 Using Checkpointing . . . . . . . . . . . . . . . . . . . 3.4 Tracing . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.5 Scripting Simics . . . . . . . . . . . . . . . . . . . . . . 3.6 Importing Files into the Simulated Machine . . . . . . 3.7 Debugging a Sample Program . . . . . . . . . . . . . . 3.8 Connecting FirstSteps to the Network . . . . . . . . . 3.8.1 Connecting a Single Machine to Simics Central

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

21 22 22 24 26 27 28 29 31 31

2

3

9

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

3

CONTENTS

3.8.2 4

Connecting Simics Central to a Real Network . . . . . . . . . . . .

Troubleshooting

34 37

II Using Simics

39

5

Glossary

41

6

Startup Options 6.1 Processor Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2 Common Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

43 43 44

7

Usual Simics Commands 7.1 Simulation . . . . . . . . 7.2 Simulation State . . . . . 7.3 Scripts . . . . . . . . . . 7.4 Modules . . . . . . . . . 7.5 Command-Line Interface

8

9

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

45 45 45 46 46 46

The Command Line Interface 8.1 Invoking Commands . . . . . . . . . . 8.1.1 How are Arguments Resolved? 8.1.2 Namespace Commands . . . . 8.1.3 Expressions . . . . . . . . . . . 8.1.4 Interrupting Commands . . . . 8.2 Help System . . . . . . . . . . . . . . . 8.3 Tab Completion . . . . . . . . . . . . . 8.4 Remote Frontend . . . . . . . . . . . . 8.4.1 Remote Frontend Limitations .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

47 47 48 48 49 49 49 51 51 53

Configuration and Checkpointing 9.1 Saving and Restoring Configurations . . . . . . . . . . . . . . . . . . . . . . 9.2 Modifying Saved Configurations . . . . . . . . . . . . . . . . . . . . . . . . 9.3 Ready-to-run Configurations . . . . . . . . . . . . . . . . . . . . . . . . . .

55 57 57 57

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

10 Script Support in Simics 10.1 Python in Simics . . . . . . . . . . . . . . . . . . . . . . 10.2 Accessing the Configuration from Python . . . . . . . 10.2.1 Configuration Objects . . . . . . . . . . . . . . 10.2.2 Creating Configurations in Python . . . . . . . 10.3 Accessing Commmand-Line Commands from Python 10.4 Script Branches . . . . . . . . . . . . . . . . . . . . . . 10.4.1 Introduction to Script Branches . . . . . . . . . 10.4.2 How Script Branches Work . . . . . . . . . . . 10.4.3 Script Branch Functions . . . . . . . . . . . . . 10.4.4 Script Branch Limitations . . . . . . . . . . . . 4

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

59 59 60 60 61 62 62 62 63 63 63

CONTENTS

11 Simics Programming Interface 11.1 The Simics API . . . . . . . . . . . . . . . . . 11.2 Haps (Event Occurrences) . . . . . . . . . . . 11.2.1 Haps Description . . . . . . . . . . . . 11.2.2 Example of Python Callback on a Hap 11.2.3 Magic Instructions . . . . . . . . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

65 65 66 66 66 67

12 Managing Disks, Floppies, and CD-ROMs 12.1 Saving Modifications to Simulated Disk . . . . . . . . . . . . 12.1.1 Using Read/Write Disks . . . . . . . . . . . . . . . . . 12.1.2 Saving a Disk Diff . . . . . . . . . . . . . . . . . . . . 12.1.3 Writing Binary Data from Simics . . . . . . . . . . . . 12.2 Copying Real Disks . . . . . . . . . . . . . . . . . . . . . . . . 12.3 Constructing a Disk from Multiple Files . . . . . . . . . . . . 12.4 Accessing Host CD-ROM . . . . . . . . . . . . . . . . . . . . 12.5 Accessing CD-ROM Image File . . . . . . . . . . . . . . . . . 12.6 Accessing Host Floppy . . . . . . . . . . . . . . . . . . . . . . 12.7 Accessing Floppy Image File . . . . . . . . . . . . . . . . . . . 12.8 Accessing Disk Images from the Host Machine . . . . . . . . 12.9 Using the /host Filesystem . . . . . . . . . . . . . . . . . . . 12.9.1 Installing the /host Filesystem on a Simulated Solaris 12.10The Craff Utility . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

69 69 70 71 72 72 74 75 75 76 76 77 78 78 79

13 Debugging Tools 13.1 Breakpoints . . . . . . . . . . . . . . . . . . . . . . 13.1.1 Memory Breakpoints . . . . . . . . . . . . . 13.1.2 Temporal Breakpoints . . . . . . . . . . . . 13.1.3 Control Register Breakpoints . . . . . . . . 13.1.4 I/O Breakpoints . . . . . . . . . . . . . . . 13.2 Using GDB with Simics . . . . . . . . . . . . . . . . 13.2.1 Remote GDB and Shared Libraries . . . . . 13.3 Symbolic Debugging Using Symtable . . . . . . . 13.3.1 Symtables and Contexts . . . . . . . . . . . 13.3.2 Sample Session . . . . . . . . . . . . . . . . 13.3.3 Common Commands . . . . . . . . . . . . 13.3.4 Symbolic Breakpoints . . . . . . . . . . . . 13.3.5 Reading Debug Information from Binaries 13.3.6 Loading Symbols from Alternate Sources . 13.3.7 Multiple Debugging Contexts . . . . . . . . 13.3.8 Scripted Debugging . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

81 81 81 82 82 82 83 84 85 85 86 87 88 88 89 89 90

14 Network Simulation 14.1 Setting up a Simulated Network . . 14.2 Connecting to a Simulated Network 14.3 Connecting to a Real Network . . . . 14.4 Manipulating the IP Routing Table .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

93 93 94 95 97

5

. . . .

. . . .

. . . .

. . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

CONTENTS

14.5 14.6 14.7 14.8 14.9

Services in ethernet-central . . . . . . . . . . . . . . . . Booting with DHCP . . . . . . . . . . . . . . . . . . . . . Booting with BOOTP . . . . . . . . . . . . . . . . . . . . Transferring Files with TFTP . . . . . . . . . . . . . . . . Troubleshooting Real Network Configuration Problems

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

97 98 98 99 99

15 Cache Simulation 15.1 Simulating a Simple Cache . . . . . . . . 15.2 Multiple Level Caches . . . . . . . . . . 15.3 Generic-Cache Features and Limitations 15.4 Observing Instruction Fetches . . . . . . 15.5 Understanding Generic-Cache Statistics

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

101 101 102 106 106 107

16 Understanding Simics Timing 16.1 Simulation Mechanism . . . . . . . . . . 16.2 Execution modes . . . . . . . . . . . . . 16.2.1 In-Order Execution . . . . . . . . 16.2.2 Out-Of-Order Execution . . . . . 16.3 Modeling Time . . . . . . . . . . . . . . 16.3.1 Default Timing Models . . . . . 16.3.2 Memory Hierarchy Interface . . 16.3.3 The Consistency Controller . . . 16.3.4 Micro-Architectural Interface . . 16.4 Event Handling . . . . . . . . . . . . . . 16.5 The Simulator Translation Cache (STC)

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

109 109 110 110 111 112 112 113 114 114 115 116

III

Extending Simics

117

17 Creating a Simics Module 17.1 Setting up a Build Environment . . . . . 17.2 Compiling Modules . . . . . . . . . . . . 17.3 Module Makefiles . . . . . . . . . . . . . 17.4 Adding Modules to the Build List . . . . 17.5 Standard Module Target Defines . . . . 17.6 Standard Module Host Defines . . . . . 17.7 User Defined Module Version Numbers 17.8 Module Loading Support . . . . . . . . 17.9 The Object Directories . . . . . . . . . . 18 Inside a Simics Module 18.1 Module Loading and Unloading . . 18.2 Implementing Module Functionality 18.2.1 Classes and Objects . . . . . . 18.2.2 Interfaces . . . . . . . . . . . 18.2.3 Events . . . . . . . . . . . . . 6

. . . . .

. . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . .

119 119 121 122 123 124 124 125 125 126

. . . . .

127 127 128 128 129 129

. . . . . . . . . . . . . . .

129 129 130 130 131 133 137 139 140 140 140 141 141 142 143

19 Adding New CLI Commands 19.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.2 Example of a new command . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.3 Argument Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

145 145 145 150

20 Creating a Device Step by Step

153

18.3

18.4 18.5 18.6 18.7 18.8

18.2.4 Haps . . . . . . . . . . . . . 18.2.5 Commands . . . . . . . . . Implementing Classes and Objects 18.3.1 Classes . . . . . . . . . . . . 18.3.2 Objects . . . . . . . . . . . . 18.3.3 Attributes . . . . . . . . . . 18.3.4 Registering Attributes . . . 18.3.5 Registering Interfaces . . . 18.3.6 Creating Objects . . . . . . 18.3.7 Examples . . . . . . . . . . Posting Events . . . . . . . . . . . . Simics Header Files . . . . . . . . . System Calls and Signals . . . . . . Text Output . . . . . . . . . . . . . Using Threads in Simics Modules .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

21 Creating a Timing Model 21.1 The Operate Function . . . . . . . . . . . . . . 21.2 Observing Instruction Fetches . . . . . . . . . 21.3 Changing the Result of Memory Operations . 21.4 Chaining Timing Models . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . .

. . . . . . . . . . . . . . .

. . . .

. . . . . . . . . . . . . . .

. . . .

. . . . . . . . . . . . . . .

. . . .

. . . . . . . . . . . . . . .

. . . .

. . . . . . . . . . . . . . .

. . . .

. . . . . . . . . . . . . . .

. . . .

. . . . . . . . . . . . . . .

. . . .

. . . . . . . . . . . . . . .

. . . .

. . . . . . . . . . . . . . .

. . . .

. . . . . . . . . . . . . . .

. . . .

. . . . . . . . . . . . . . .

. . . .

. . . . . . . . . . . . . . .

. . . .

. . . . . . . . . . . . . . .

. . . .

. . . . . . . . . . . . . . .

. . . .

. . . . . . . . . . . . . . .

. . . .

. . . .

157 158 159 159 159

22 Creating a Cache Model 161 22.1 Using the Sample Cache Code . . . . . . . . . . . . . . . . . . . . . . . . . . 161 22.2 Using the Generic Cache Code . . . . . . . . . . . . . . . . . . . . . . . . . 161

Index

163

7

8

Part I

Starting with Simics

9

Chapter 1

Introduction Simics is an efficient, instrumented, system level instruction set simulator. • Whereas an emulator is focused on executing a program as quickly and accurately as possible, a simulator, in addition, is designed from the ground up to gather information on the execution and in general be a flexible tool. Simics is more of a platform on which to build simulation-based tools than just a single program. • efficient means that Simics is designed to be sufficiently fast to run realistic workloads, typically better than 100x slowdown in comparison with native execution. This can seem slow in comparison to fast emulators, but Simics provides a wide range of features and facilities. In fact, in its class of tools, Simics is the fastest simulator ever implemented. • instrumented means that Simics was designed not to run just the target system programs, but to gather a great deal of information during runtime. Many simulators are simply fast emulators with instrumentation added as an afterthought, leading to a situation where when the tool is used as intended (with high levels of information-gathering enabled), it slows down considerably. Simics, in contrast, is specifically designed to achieve high performance even with a high level of instrumentation and under very large workloads. Simics provides a variety of statistics in its default configuration and allows various add-ons to be developed by power users and plugged into the simulator. • Simics is system level, meaning that it models a target computer at the level that an operating system acts. Thus, Simics models the binary interfaces to buses, interrupt controllers, disks, video memory, etc. This means that Simics can run run anything that the target system can, i.e., arbitrary workloads. Simics can boot unmodified operating system kernels from raw disk dumps. • instruction set simulator means that Simics models the target system at the level of individual instructions, executing them one at a time. This is the lowest level of the hardware that software has ready access to. Simulating at this level allows Simics to be system level, yet still permits an efficient design. 11

1.1. Hosts and Targets

Simics fully virtualizes the target computer, allowing simulation of multiprocessor systems as well as a cluster of independent systems, and even networks, regardless of the simulator host type. The virtualization also allows Simics to be cross platform. For instance, Simics/SunFire can run on an Linux/x86 system, thus simulating a 64-bit bigendian system on a 32-bit little endian host. The end uses for Simics include program analysis, computer architecture research, and kernel debugging. The analysis support includes code profiling and memory hierarchy simulation (i.e., cache hierarchies). Debugging support includes a wide variety of breakpoint types. The support for system-level simulation allows operating system code to be developed and analyzed.

1.1

Hosts and Targets

Two very important terms used throughout the Simics manuals are host and target, which are explained below. You can find a longer list of terms used in the glossary (see chapter 5). • host defines the computer on which you are running Simics. It can also refer to the architecture (x86) or the model (Sun SunFire) of computer that runs the simulator, or to the host platform (combination of an architecture and an operating system, like x86-linux). • target refers to the computer simulated by Simics. It can also refer to the architecture or the model of computer simulated. Simics exists in a variety of target–host combinations. The standard host platforms for Simics are: • Linux/x86 Compiled for Red Hat Linux 6.2 with GCC, but works on many other Linux distributions as well as later versions of Red Hat Linux. • Solaris/UltraSPARC 32-bit Sun Forte 6.2 compiled versions. Requires Solaris 8 or newer. • Windows 2000 Compiled with GCC. This version also works on Windows XP. Additional host platforms for Simics, with only limited support: • Solaris/UltraSPARC 64-bit Compiled with Sun Forte 6.2. Requires Solaris 8 or newer. You can refer to the chapter 6 to get a full list of all the processor models available in Simics.

1.2

Simics Targets - Fully Supported

The following list contains all fully supported Simics targets. Fully supported means that they are available for download and evaluation, and can run on all standard host platforms. 12

1.3. Simics Targets - Limited Support

1.2.1

Simics/SunFire

Simics/SunFire simulates the Sun Enterprise 3000-6500 server series running Solaris or Linux. A variety of SBus and PCI based devices are supported, such as SCSI, FibreChannel, and graphics cards. Simics/SunFire is also available in out-of-order mode (see chapter 16 and the Simics Out-of-Order Guide for more information). Simics/SunFire runs on all standard host platforms, as well as 64-bit Solaris.

1.2.2

Simics/Serengeti

Simics/Serengeti simulates the Sun Fire 3800-6800 server series from Sun running Solaris. A variety of PCI based devices are supported, such as SCSI, Fibre-Channel, and graphics cards. Simics/Serengeti runs on all standard host platforms, as well as 64-bit Solaris. Simics/Serengeti is also available in out-of-order mode (see chapter 16 and the Simics Out-of-Order Guide for more information).

1.2.3

Simics/x86

Simics/x86 simulates various x86 class processors, ranging from 486sx to Pentium 4, and is capable of booting Linux up to version 2.4, Windows NT 4.0, 2000 and XP in both single-processor and multi-processors (SMP) mode. Simics/x86 includes various PC devices needed to boot the virtual PC such as graphic controllers, bus controllers, floppy and hard disks. Simics/x86 runs on all standard host platforms.

1.2.4

Simics/x86-64

Simics/x86-64 simulates a PC system with a processor conforming to AMD’s x86-64 architecture. It can run a large number of operating systems in both the IA32 compatible legacy modes and in x86-64 native mode. Simics/x86-64 runs on all standard host platforms.

1.3

Simics Targets - Limited Support

The following list contains Simics targets with limited support. Limited support targets may not be available on all host platforms, and packages may only be available for download and evaluation on request.

1.3.1

Simics/Alpha

Simics/Alpha models the Alpha 21164 (also known as EV5) implementation of the Alpha architecture. It includes device models and configurations for systems based on the 21174 (Pyxis) chipset, similar to the AlphaPC 164LX. 13

1.4. This Document

Simics/Alpha is capable of booting Red Hat Linux 6.0 and 6.2. It has been tested with Linux miniloader (MILO). Simics/Alpha runs on all standard host platforms.

1.3.2 Simics/PPC Simics/PPC models the 32 bit PowerPC 750 and 7450 (including AltiVec) processors, including devices to simulate Artesyn’s PM/PPC card. The Artesyn PM/PPC is a complete real-time computer solution in a very compact, industry standard form-factor. It is designed to allow communication equipment manufacturers to add compute functionality to a baseboard, such as a T1/E1 or ATM interface board, and provide the localized horsepower necessary for applications such as protocol processing, data filtering or I/O management. Simics/PPC runs on all standard host platforms.

1.3.3 Simics/IA-64 Simics/IA-64 models the Intel Itanium and Itanium2 processors. It includes device models to simulate a complete system based on the 460GX chipset, and is capable of booting Linux 2.4. Simics/IA-64 runs on all standard host platforms.

1.3.4 Simics/ARM Simics/ARM models a generic ARMv5 processor with minimal implementations of the devices from the Intel StrongARM processor that are needed to boot a minimal Linux configuration. Simics/ARM runs on all standard host platforms.

1.3.5 Simics/MIPS Simics/MIPS models the 32 bit MIPS-4Kc processor with a limited set of devices from the MIPS Malta reference board. Only the devices needed in order to boot Linux have been implemented. Simics/MIPS runs on all standard host platforms.

1.4

This Document

The remainder of this document provides an overall description of Simics’ capabilities, environment and user interface. Scripts, screen dumps and code fragments will be presented in a monospace font. Sometimes, artificial line breaks may be introduced to prevent the text from being too wide. When a break is introduced, it is shown as a small arrow pointing to the next line. It means that the text that has been interrupted continues on the next line. 14

1.5. Other Documentation

This is an artificial line-break that shouldn’t be typed. The directory [simics] will be used to refer to where Simics is installed when giving path examples, like [simics]/README

1.5

Other Documentation

Release notes for a Simics version is available in the README_ file (where is the major Simics version number). This file is updated with information for each patch release of Simics (For example, [simics]/README_1.4). For complete descriptions of Simics commands, APIs, loadable modules etc., please refer to the Simics reference manuals. The reference manuals are target specific; the following exist: • Simics/Alpha Reference Manual • Simics/ARM Reference Manual • Simics/IA-64 Reference Manual • Simics/MIPS Reference Manual • Simics/PowerPC Reference Manual • Simics/Serengeti Reference Manual • Simics/SunFire Reference Manual • Simics/x86 Reference Manual • Simics/x86-64 Reference Manual In addition a separate reference manual exists which covers the commands available in Simics Central (used for creating networks of simulators): • Simics Central Reference Manual To get a description of the different virtual target machines available as examples, you can consult the target guides: • Simics/ARM Target Guide • Simics/IA64 Target Guide • Simics/MIPS Target Guide • Simics/PowerPC Target Guide • Simics/Serengeti Target Guide 15

1.5. Other Documentation • Simics/SunFire Target Guide • Simics/x86 Target Guide There is also an online technical FAQ available at: • http://www.simics.net/support

16

Chapter 2

Installation This chapter describes how to handle encrypted files, licenses and disk dumps, as well as how to install Simics for several users.

2.1

Licenses

If you received a license file for one computer, just copy it in the [simics]/licenses/ directory. It will be automatically recognized and used by Simics.

2.2

Flexlm Floating Licenses

Simics needs a license server for floating licenses. The license server used is FLEXlm v8.1 from GLOBEtrotter. Below we will briefly describe how to set up the license server. For further information on how to manage the server please consult the end user manual which can be found at http://www.globetrotter.com/flexlm/lmgrd.shtml More information may also be available from the http://www.simics.net web site. Note: FLEXlm is a very common license technology, and if you are a corporate user then it is likely that you already have a centrally managed corporate server. Ask your system administrator. To run Simics the first time, a few files should be installed, and a license server must be running. The files are located in the Simics distribution under [simics]/host/sys/ flexlm/bin, e.g., [simics]/x86-linux/sys/flexlm/bin: • lmgrd — The License Manager Daemon (server) • lmutil — FLEXlm utility program(s) • vtech — The vendor daemon from Virtutech 17

2.2. Flexlm Floating Licenses

A license file from Virtutech is also needed (usually sent via e-mail), that specifies your licenses. The license file is typically called simics.lic. lmgrd, lmutil and vtech can be installed anywhere in the system, but /usr/ local/flexlm/bin/ is the recommended directory. The license file, e.g., simics. lic, should then be placed in the [simics]/licenses/ directory. This is the default location for a license file, meaning that Simics will find it automatically. To override this, the environment variable LM_LICENSE_FILE (or VTECH_LICENSE_FILE) can be set to the name of the license file or to the directory where it resides. It can also be set to @license-host (i.e., the machine running the license server) if the license file cannot be reached through the file system. In this case the license server will know the location of the license file. A typical license file looks like this: SERVER server ANY USE_SERVER # change the path to where the license daemon (vtech) is located VENDOR vtech /usr/local/flexlm/bin/vtech FEATURE simics vtech 1.0 3-oct-2003 20 AAFBC87969B5 \ VENDOR_STRING=comm # FEATURE v9_on_x86_linux vtech 1.0 3-oct-2003 20 A1BBBC7B2FBE

where server is the name of the host that will run the license server. This can be changed by the user. The VENDOR line specifies the vendor and where to find the vendor daemon. Edit this line. FEATURE specifies the type of license and for what it is used. In this case it is 20 commercial floating licenses for Simics SPARC-V9 v1.0 on x86 host running Linux with expire date 3-oct-2003. The last hexadecimal codes are checksums which asserts that the license file is not altered in an unauthorized way by the user. A license server is started as follows: joe@server:˜$ lmgrd -c license-file Remember to run lmgrd on the server host specified in the license file, in the example it is “server”. Since lmgrd does not need root privileges it is recommended to run it as a user. If the -c option is not given, the license server will try to find the license file license. dat in [simics]/licenses, or find it using the LM_LICENSE_FILE variable. The server will log all actions to stdout, unless a log file is specified by the -l log-file option. lmgrd will find the vendor daemon and start it. All communication between the licensed software and the vendor daemon goes via the license server (lmgrd). It is the vendor daemon that keeps track of products and number of licenses from a particular vendor, thus only one license server is needed to run software from several vendors. Once the license server is started, Simics can be run like any program and the communication to the license server should be transparent to the user. When Simics is started it will ask for a license from the vendor daemon and, if the user is authorized and available licenses exist, Simics will check-out a license and run. On exit, Simics will 18

2.3. Multi-User Environment

give back the license to the daemon (check-in). If Simics ever crashes or exits abnormally, a license may be lost since it was never checked in. If this happens, the license server needs to be restarted. To shut down the license server and the vendor daemon type: joe@enterprise:˜$ lmutil lmdown and the server will go down. Note: Once flexlm has successively checked out a license it will add the path to the license file (if it is not already present) to the .flexlmrc file in the user’s home directory. This can be very confusing since flexlm will be able to find license files not longer present in the LM_LICENSE_FILE environment variable. If you have trouble with this then delete the .flexlmrc file.

2.3

Multi-User Environment

Simics can be installed for a multi-user environment on Linux and Solaris. Simics must first be installed as described above, and configure has to be run in the appropriate host directories. Each user, who need read access to the master Simics directory, then runs the script [simics]/scripts/user-install.sh to create a personal Simics user installation. The Simics user tree has the same structure as the master tree, except that most of the files and directories are actually links to the master tree’s files. Some files are however specific to the user and can be modified freely in the user tree: • home/ contains the configuration of the target machines. • import/ links the additional files needed and not provided along with Simics (disk dumps). • src/ contains the framework for developing new Simics modules (including the examples). • host (such as x86-linux) contains the object files and specific modules or librairies developed by the user. To be able to build own modules in the user tree, the master tree should have been configured for building as well (by running configure in the host directory). The user can simply run configure in its own tree to handle eventual small differences in the build environment. Modules developed in the user tree override those provided in the master tree. In the same way, source files present in the user tree are chosen preferentially to those in the master tree. For more information regarding modules and builds, please consult chapter 17. 19

2.4. .tf Encoded Files

2.4

.tf Encoded Files

Some of the files proposed for download are encrypted in the .tf format. To decrypt them, you will need to download an external decoder called tfdecode. It is available at ftp://ftp.simics.net/pub as archive files. When you uncompress the archive, you will get an executable file that can be use in the following way: bash# cat file.tf | tfdecode 0x1 0x2 0x3 0x4 > file where 0x1, 0x2, 0x3 and 0x4 are the decryption keys corresponding the the package. If no pre-compiled binaries is matching your system, you can also download the source archive and compile tfdecode by yourself.

2.5 Getting Disk Images In order to run a real operating system on Simics, you would need to start from the ground and install it from a CD on your new empty simulated workstation. To speed up the process, Virtutech provides disk images (also called disk dumps) of freely available operating systems for download. Since these images are very big, they are not included with the Simics distributions. If you have a Simics CD, some images may have been provided along with the Simics binaries. These additionnal files can be downloaded on Virtutech web site at http://www. simics.net/download. These files should be placed in the [simics]/import/target directory, where target is the type of computer simulated (for example, the enterprise dump should be placed in the [simics]/import/x86/ directory, since enterprise is a x86 simulated workstation). Note: Due to licensing issues, Virtutech distributes only freely available operating systems. If you wish to simulate a commercial system like Windows or Solaris, you will have to install it by yourself. The Target Guides provide information on how to perform standard installations.

20

Chapter 3

First Steps First Steps with Simics is a step-by-step guide describing how to perform some common tasks with Simics. The guide is based on a target computer known as FirstSteps. FirstSteps is a simulated Pentium II machine running a very small Linux Debian 3.0. First, a few conventions. In this document, text written like this: Simics Output this is output from Simics prompt> this is a command the user should type [...]

is output from Simics itself. The [...] means that some output has been removed. Text written like this: Target Output this is output from the simulated machine prompt> this is a command the user should type on the simulated machine [...]

is output from the simulated machine. Output from Simics should not be confused with the output from the simulated machine. In the case of FirstSteps, the output from the simulated machine comes to a VGA console (it actually shows the output of a simulated Voodoo3 graphics card). This console opens as a separate window, with the title “Simics Console: con0”. So, all input and output for the simulated machine goes into the VGA console window, and all input and output for Simics goes to the terminal where you started Simics. 21

3.1. Downloading FirstSteps Disk Image

3.1

Downloading FirstSteps Disk Image

This tutorial relies on a disk image called firststeps1.craff. Check for this file in the [simics]\import\x86 directory of your installation (where [simics] represents the directory where Simics is installed on your computer). If you do not find it, you need to download it from Virtutech website, otherwise you can directly start the tutorial. The download area for disk dumps is at http://www.simics.net/download. Download the file firststeps1.craff and place it into the [simics]/import/ x86 directory of your installation. You are now ready to run the tutorial.

3.2

Booting

We are now ready to start Simics and boot FirstSteps: Simics Output bash$ cd [simics]/home/firststeps bash$ ./simics -x firststeps.simics Simics startup wrapper. Copyright (c) 2000-2002 Virtutech AB. Checking out a license... done: academic license. +----------------+ | Virtutech | | Simics/x86 | +----------------+ www.simics.com Type Type Type Type

Copyright 1998-2002 by Virtutech, All Rights Reserved Version: Simics 1.4.0 Compiled: Thu Sep 5 09:18:32 CEST 2002 Simulated processor: x86 (P6 cpuid fpu vme de [...] "Virtutech" and "Simics" are trademarks of Virtutech AB

’copyright’ for details on copyright. ’license’ for details on warranty, copying, etc. ’readme’ for further information about this version. ’help help’ for info on the on-line documentation.

Added to search path: ../../import/x86 Added to search path: ../../import/x86_64 [gfx-console]: Connecting to display: :0.0 [disk0_image] Opened subfile ’first-steps1.craff’ (format craff) [rom0_image] Opened subfile ’rombios-2.35’ (format raw) [rom0_image] Opened subfile ’voodoo3-pci-bios.bin’ (format raw) [gfx-console]: Using MIT-SHM extension [con0] Input disabled [con0] Setting poll-rate: 50 Hz +--------------------------------+ | Welcome to the Simics tutorial | +--------------------------------+ If you do not know what to do here, it is probably

22

3.2. Booting

because you are not reading the Simics tutorial. Check the chapters 3 in the User Guide to start the tutorial. To boot the FirstSteps machine, just type the command ’c’ followed by enter. To exit Simics, use the command ’q’ followed by enter. simics>

The -x argument tells Simics to start and run a script, in this case firststeps. simics. If everything goes well, you will see a blank window popping up. This is the VGA output console. To start the simulation, use the command continue. Since this is a very commonly used command, there is an alias for it, c. Note: You can get help on any command by typing help command.

Simics Output simics> c

You will see the usual BIOS messages, then LILO will start loading and uncompressing the Linux kernel. Let Simics run and after a few minutes (depending on how fast your machine is, of course), you will see the familiar login prompt as shown in figure 3.1. Note: If you only see a blank screen, Linux may have started a screen saver. Please continue the tutorial: as soon as you press a key in the simulated machine, you will see the prompt screen reappear. Now, note that FirstSteps VGA console says “input disabled” in the title bar. This means that the console does not accept any input. This is useful to avoid random keyboard events disturbing the deterministic properties of the simulation. Our first action is therefore to enable the input so we can login. This is done by giving Simics the command con0.enable-input. But, since FirstSteps is currently running, we need to interrupt it with a control-C first. Press control-C in the Simics terminal (i.e., the window were you started Simics), then type the command con0.enable-input: Simics Output --- control-C --simics> con0.enable-input [con0] Input enabled simics> c

23

3.3. Using Checkpointing

Figure 3.1: Linux prompt

Note: You can issue the con0.enable-input command at any time during the boot process; press control-C in Simics terminal, type the command, and continue by typing c). The text “input disabled” should now have disappeared from FirstSteps VGA console. Now, we should try to login. FirstSteps has no user accounts, so we login as root with no password. You can try to run a few commands on the console. Remember that the simulated operating system is configured for an american keyboard. Note: If the VGA console does not respond, first make sure that Simics is actually running (type c at the simics> prompt). Remember that if Simics is not running, the CPU of the target machine is not running either. Do not be surprised if output suddenly appears on the VGA console when you continue the simulation. This is due to the window’s keyboard buffer flushing out what you have been typing when the simulated cpu was not running.

3.3

Using Checkpointing

In order to avoid booting FirstSteps every time, we use the facility known as configuration checkpointing or simply checkpointing. This enables Simics to save away the entire state of a simulated machine into a portable format to be loaded at a later time. The state is saved using the command write-configuration. 24

3.3. Using Checkpointing

Simics Output --- control-C --simics> write-configuration "fs-config-1.config" [disk0_image] Opened subfile ’fs-config-1.config.disk0_image’ (format craff) [mem0_image] Opened subfile ’fs-config-1.config.mem0_image’ (format craff) [rom0_image] Opened subfile ’fs-config-1.config.rom0_image’ (format craff) simics>

Since Simics only supports one configuration per session, we must quit Simics in order to restart the simulation from the saved configuration. Simics Output simics> quit [disk0_image] Closed craff file ’first-steps1.craff’. [disk0_image] Closed craff file ’fs-config-1.config.disk0_image’. [mem0_image] Closed craff file ’fs-config-1.config.mem0_image’. [rom0_image] Closed raw file ’rombios-2.35’. [rom0_image] Closed raw file ’voodoo3-pci-bios.bin’. [rom0_image] Closed craff file ’fs-config-1.config.rom0_image’. Simics license checked in! bash$

The FirstSteps VGA console should now have disappeared. We start Simics again, but this time without -x firststeps.simics, since we have our own configuration to start from. At the simics prompt, do: Simics Output bash$ ./simics Simics startup wrapper. Copyright (c) 2000-2002 Virtutech AB. Defaulting to host x86-linux. Set SIMICS_HOST to override. Checking out a license... done: academic license. [...] Type ’help help’ for info on the on-line documentation. simics> read-configuration "fs-config-1.config"

and the machine comes back to the exact same state (including the VGA console, of course). You can continue the simulation again and check that everything is the same. To learn more about Simics configurations, you can read the chapter 9 in the User Guide. Simics includes many pre-configured machines. They are described in the Simics Target Guides. 25

3.4. Tracing

3.4

Tracing

This section describes how to use the tracing facility provided by the trace module. It enables the user to get all instructions, memory accesses, and exceptions printed out in the order in which they occurred. First, let us restart Simics with the initial configuration: Simics Output bash$ ./simics -x firststeps.simics Simics startup wrapper. Copyright (c) 2000-2002 Virtutech AB. Defaulting to host x86-linux. Set SIMICS_HOST to override. [...] simics>

Then load the trace module by typing: Simics Output simics> load-module trace [trace module] Created a trace0 object Module trace loaded simics>

The trace-module tells us that it has created an object named trace0 that will handle the tracing. This object supports two commands, trace0.start and trace0.stop; what they do should be obvious. Let us try to trace the first 10 instructions executed when booting FirstSteps. Simics Output simics> trace0.start Tracing enabled simics> c 10 [...] inst: [ 1] CPU [...] inst: [ 2] CPU [...] inst: [ 3] CPU [...] inst: [ 4] CPU [...] inst: [ 5] CPU [...] inst: [ 6] CPU [...] inst: [ 7] CPU [...] data: [ 1] CPU [...] data: [ 2] CPU [...] inst: [ 8] CPU [...] inst: [ 9] CPU [...] inst: [10] CPU [cpu0] simics>

26

0 0 0 0 0 0 0 0 0 0 0 0 0

e9 68 e0 b8 4a 7b ff e0 b8 00 90 8e c0 bb ff ff 26 87 1e 20 fd Vani WB Read 2 bytes Vani WB Write 2 bytes 83 fb 00 0f 85 f1 ff b8 fe ff 0 0 0 0 0 0 89 c4

jmp 0xe05b mov ax,0x7b4a jmp ax mov ax,0x9000 mov es,ax mov bx,0xffff xchg word [...] 0x0 0xffff cmp bx,0x0 jne 0x7b4f mov ax,0xfffe mov sp,ax

3.5. Scripting Simics

To learn more about the trace module, you can have a look at the source code provided in [simics]/src/extensions/trace/. The User Guide’s part III contains generic information about understanding and writing Simics modules.

3.5

Scripting Simics

Let us use a Simics script to do a somewhat more complex trace. The following script runs one instruction at a time until the register esp is modified. Then it turns on tracing and traces the following ten instructions. It is available as the script file trace.simics in the firststeps/ directory. # trace.simics load-module trace @start_cycle = conf.cpu0.cycles @esp = read_reg_cmd("cpu0","esp") @while read_reg_cmd("cpu0","esp") == esp: SIM_continue(1) @print "CPU has executed", conf.cpu0.cycles - start_cycle, "cycles" @print "%esp has changed. Starting trace and running 10 instructions." trace0.trace-start run 10

Simics uses Python as its internal scripting language. By prefixing a line with @, we tell the command line to evaluate the line as a Python statement instead of a Simics command. We can run this script: Simics Output bash$ ./simics -x firststeps.simics -x trace.simics [...] [trace module] Created a trace0 object Module trace loaded CPU has executed 11 cycles %esp has changed. Starting trace and running 10 instructions. Tracing enabled [...] inst: [ 1] CPU 0 b8 00 00 [...] inst: [ 2] CPU 0 8e d8 [...] [...] data: [ 4] CPU 0 Vani WB Write 2 bytes [cpu0] 0 0 0 0 0 0 0 89 e5 simics>

27

mov ax,0x0 mov ds,ax 0x0 mov bp,sp

3.6. Importing Files into the Simulated Machine

The script tells us that esp has changed after 11 cycles, and the first instruction executed after that is mov ax,0x0 (at address cs:0x00007b63). Note: You can also run the script from Simics’ command-line by using the runcommand-file command. To learn more about Simics’ scripting capabilities, you can read the chapters 10 and 11 in the User Guide.

3.6

Importing Files into the Simulated Machine

FirstSteps is configured with the /host filesystem functionality. The /host filesystem allows you to mount your real file system inside the simulated machine and to access it directly. Let us load the previously saved checkpoint and import some files into the simulated machine. The -c option tells Simics to run the read-configuration command on the specified file after it has loaded. Simics Output bash$ ./simics -c fs-config-1.config [...] simics> c

Then at the simulated machine prompt, mount the directory /host: Target Output firststeps:˜# mount /host [hostfs] mounted firststeps:˜# ls /host bin etc initrd boot floppy lib cdrom home lost+found dev host mnt firststeps:˜#

opt proc root sbin

tmp usr var vmlinuz

You can copy files from your real machine on the simulated disk and use them inside your simulated machine. Note: The /host filesystem is mounted read-only, that is you can not write files from the simulated machine to your real machine. We also recommend that you copy files on the simulated disk before you execute them instead of running them directly from the /host filesystem.

28

3.7. Debugging a Sample Program

To learn more about disk management in Simics, you can read the chapter 12 in the User Guide. The Target Guides also contains information on how to add a new disk to a pre-configured machine.

3.7

Debugging a Sample Program

Simics provides many tools for debugging simulated programs. Here we will use the module symtable to trace a very simple program. Since you have already mounted the /host filesystem, you can copy the example file [simics]/home/firststeps/debug_example into the simulated machine. Just in case, they are also available in the /root/example/ directory in the simulated machine. Target Output firststeps:˜# cp /host/home/joe/simics/home/firststeps/debug_example .

Note: The source code of this small sample program is available as debug_example.c in the firststeps/ directory. The executable was compiled for a GNU Libc 2 system. If you recompile it, do not forget to include debugging symbols to be able to run the tutorial. If you try to run it as well, you will get the following output: Target Output firststeps:˜# ./debug_example Allocating space Counting Primes less than 1000000: 78498 Done firststeps:˜#

In Simics, we will load the symtable module and load the symbol table corresponding to debug_example. Simics Output --- control-C --simics> load-module symtable Module symtable loaded simics> new-symtable file = debug_example Created symbol table ’debug_example’ for context ’primary-context’ Loading symbols: debug_example [symtable] Symbols loaded at 0x80483b0

29

3.7. Debugging a Sample Program

simics>

The symbol table is now loaded. However, to get the right code line to be printed as well, we need to specify the path of the source file debug_example.c. symtable has created a debug_example object. We will use the source-path command to tell symtable where to find the source file. This command can work in different ways; we will use it to replace the wrong directory name included in the file (/disk01/joe) by the directory where the file debug_example.c is actually located: Simics Output simics> debug_example.source-path path = /disk01/joe>[simics]/home/firststeps simics>

where [simics] is the absolute Simics directory (i.e, like in /home/joe/simics/ home/firststeps). Take care that there is a > between the two paths to translate. Note: If you recompile the example yourself, you will not need to change the source path, because the absolute path included along with the debugging information will be correct. The debug_example program is using a very interesting feature of Simics called a “magic instruction”. This is an instruction that doesn’t affect the state of the simulated machine, but tell Simics that this specific “magic” instruction has run and allows to place breakpoints or other interesting events when the instruction is encountered.. The source code of debug_example has a magic instruction placed just before the main loop of the program. We start by telling Simics to stop the simulation every time a magic breakpoint is reached with the magic-break-enable command. We continue the simulation, then run debug_example inside the simulated machine and Simics will automatically stop when the magic instruction is reached. Simics Output simics> magic-break-enable simics> c --- after some simulation time --Magic breakpoint Pseudo exception 1027 caught [cpu0] [...] 66 87 db magic breakpoint (xchg bx, bx) main (argc=1, argv=0xbffffe14) at /disk01/joe/debug_example.c:47 47 MAGIC_INSTRUCTION; simics> si [cpu0] [...] c7 45 fc 02 00 00 00 mov dword ptr 0xfc[ebp],0x2 49 for (i=2; i si

30

3.8. Connecting FirstSteps to the Network

[cpu0] [...] 49 for (i=2; simics> si [cpu0] [...] 49 for (i=2; simics>

81 7d fc 3f 42 0f 00 i lance0.connect net0 simics> c

The command lance0.connect plugs in the (virtual) ethernet-cable running from FirstSteps into the switch (named net0, simulated by Simics Central). In our Simics Central window we will see some activity: Simics Output Connecting: /tmp/simics-19421 Connection established with local Simics Installing new connection: fd 6, index 2 Enough Simics processes (1) to start running!

32

3.8. Connecting FirstSteps to the Network

[server] got GETMOD message for module ethernet-central from Simics (id 0, mod 0, sub 0) [ether0] Device registering with Ethernet Central: [ether0] simics: simics at localhost [ether0] device: lance0 [ether0] network: net0 [ether0] requested addr: 10:10:10:10:10:34 [ether0] assigned addr: 10:10:10:10:10:34

This means that Simics Central has recognized that a network device with ethernet address 10:10:10:10:10:34 has been connected. Note that there will be no traffic until FirstSteps has set up the network device eth0. The Linux distribution running on FirstSteps will automatically configure the network and default routes to the local network and the gateway provided by Simics Central. When the boot sequence is finished, we can enable console input again, login and then try to have a look at the configuration and ping Simics Central: Target Output firststeps:˜# ifconfig eth0 Link encap:Ethernet HWaddr 10:10:10:10:10:34 inet addr:10.10.0.17 Bcast:10.10.0.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:32 errors:0 dropped:0 overruns:0 frame:0 TX packets:32 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:100 RX bytes:3013 (2.9 kb) TX bytes:2911 (2.8 kb) Interrupt:7 Base address:0x300 DMA chan:4 lo

Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:3924 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)

firststeps:˜# ping -c 5 central PING central.network.sim (10.10.0.1): 56 data bytes 64 bytes from 10.10.0.1: icmp_seq=0 ttl=32 time=151.1 64 bytes from 10.10.0.1: icmp_seq=1 ttl=32 time=151.1 64 bytes from 10.10.0.1: icmp_seq=2 ttl=32 time=151.1 64 bytes from 10.10.0.1: icmp_seq=3 ttl=32 time=151.1 64 bytes from 10.10.0.1: icmp_seq=4 ttl=32 time=151.1

ms ms ms ms ms

--- central.network.sim ping statistics --5 packets transmitted, 5 packets received, 0% packet loss round-trip min/avg/max = 151.1/151.1/151.1 ms firststeps:˜#

33

3.8. Connecting FirstSteps to the Network

Since we have a configured local network, it is time to save a checkpoint so we do not need to reboot FirstSteps. Use control-C on the Simics FirstSteps terminal and save the configuration: Simics Output --- control-C --simics> write-configuration fs-network

3.8.2

Connecting Simics Central to a Real Network

Note: To do the following, you need root access on the host machines you are working with. If you do not have root access or if you are not used to doing network configuration, contact your system administrator for assistance. Simics Central also allows routing to and from a real network, i.e., the network of the host machine(s). For this to happen, we need to configure the simulated machine to use Simics Central as gateway, and also configure the machine on the real network to use Simics Central as a router to the simulated network. Note: Simics Central can not route traffic between the simulated network and the machine it is running on. This means that you cannot communicate with the simulated network from the machine on which Simics Central is running. To connect Simics Central to the real world, we need to be running Simics Central as the root user on the host machine (to access the network device). To follow the example given below, start Simics Central as root on a different computer than the one FirstSteps is running on, and run the command ether0.connect-real-network. Simics Output bash$ telnet another_computer bash$ su password: bash# ./simics -x central.simics Simics startup wrapper. Copyright (c) 2000 Virtutech AB. Defaulting to host x86-linux. Set SIMICS_HOST to override. [...] simics> ether0.connect-real-network Installing new connection: fd 8, index 2 [ether0] initializing network real-net: [ether0] net: 10.0.0.0 [ether0] netmask: 255.255.255.0 [ether0] broadcast: 10.0.0.255

34

3.8. Connecting FirstSteps to the Network

[ether0] own ip: 10.0.0.50 [ether0] Device registering with Ethernet Central: [ether0] simics: simics central [ether0] device: pseudo device [ether0] network: real-net [ether0] requested addr: 10:10:10:10:10:10 [ether0] assigned addr: 10:10:10:10:10:10 simics> c

Now, if you want to connect from the real world to the simulated machine, you will need to add a route on your real machine to tell it to send the network packets to the machine running Simics Central. You can do that with the command: bash# /sbin/route add -net 10.10.0.0 netmask 255.255.0.0 gw another_computer

where another_computer is the name of the machine running Simics Central. The syntax for the route command may vary between operating systems, the syntax above is for Linux. You need to add a route on each machine from where you want to reach the simulated network. For the next example to work, you need to set up a route on a real machine that we will try to ping to later on. You will probably need to be root to run the command. Let us now restart FirstSteps from our previous checkpoint: Simics Output bash$ ./simics -central another_computer -c fs-network Simics startup wrapper. Copyright (c) 2000-2002 Virtutech AB. Checking out a license... done: academic license. [...] [rom0_image] Opened subfile ’fs-network.rom0_image’ (format craff) simics> c

FirstSteps is already configured with a default route with central as gateway, so we can ping from FirstSteps to a real machine: Target Output firststeps:˜# ping -c 5 real-machine.virtutech.com PING real-machine.virtutech.com (10.10.10.10) 56 bytes of data. 64 bytes from real-machine.virtutech.com (10.10.10.10): icmp_seq=0 64 bytes from real-machine.virtutech.com (10.10.10.10): icmp_seq=1 64 bytes from real-machine.virtutech.com (10.10.10.10): icmp_seq=2 64 bytes from real-machine.virtutech.com (10.10.10.10): icmp_seq=3 64 bytes from real-machine.virtutech.com (10.10.10.10): icmp_seq=4 --- real-machine.virtutech.com ping statistics --5 packets transmitted, 5 packets received, 0% packet loss

35

ttl=254 ttl=254 ttl=254 ttl=254 ttl=254

[...] [...] [...] [...] [...]

3.8. Connecting FirstSteps to the Network

round-trip min/avg/max = 94.342/98.551/99.619 ms firststeps:˜#

That’s it! The simulated machine can communicate with the exterior world. You can now transfer files, send mail or even browse the web (but you will need a more complete machine than FirstSteps: have a look at Enterprise!). Note: If you try to connect the simulated machine from the exterior world, you need to specify its IP address since your real machine does not know which DNS to ask to the get a name translation. To learn more about simulating networks with Simics-central, you can read chapter 14 in the User Guide.

36

Chapter 4

Troubleshooting Simics complains about not finding Python You need to have Python 2.2.x installed for Simics to run, since all the commandline interface is Python-based. You can download Python at http://www.python. org/download. Simics doesn’t find any license When starting, Simics tries to check out your license and it will not start if it can’t find a valid one. Check the following: • If you have a single computer license, check that the corresponding license file is in the simics/licenses/ directory. • If you have a floating license, check that the corresponding license file is in the simics/licenses/ directory. Simics needs to know which server to contact to check out the license. Check as well if the server is reachable from your machine, and if the license server is running. • A license file is essentially a text file. You can check in the file if the license has expired. As soon as it does, the license won’t be valid anymore. • If you change your license, you may have troubles with the caching system used by FlexLM. Try to delete the file ˜/.flexlmrc and start again Simics. Simics reports a crash and switch to safe mode This means you found a bug in Simics. You can report it through the Simics Forum. Try to include as much information as possible for us to reproduce the crash. If the crash is an assertion, this means Simics has reached a state that shouldn’t be allowed. Please report the full assertion text. If you are developing your own module, please check carefully that your module is not responsible for the crash, since it is loaded as a part of Simics and may crash it just as well as our own code. In safe mode, you may still issue commands. It is recommended to save the configuration and restart Simics. 37

Simics quits after 100000 errors By default, when Simics has received 100000 error messages, it assumes this was too many errors for a normal simulation and stops. If this is not the behaviour you want, you can set the maximum error messages count through the simerrmax attribute in the sim object. Simics Central does not connect to the real network Check that you run Simics Central as root to have a direct access to the network device. Check the section 14.9 to get more information about diagnosing and solving network problems.

38

Part II

Using Simics

39

Chapter 5

Glossary • callback — A user-defined function installed so that it will be called from Simics, for example when a hap occurs. • checkpoint — A number of files, together constituting a simulation state. Simics can save its current state as a configuration checkpoint. • CLI — See Command Line Interface. • code profile — A listing of source code or assembler instructions where each line has an array of counters attached. Predefined counters include the number of times line has been executed, the number of times branching from a line, and the number of times branching to a line. • Command Line Interface — The default Simics command-line (user interface). It uses a simple language implemented in Python, and is variously called the Simics “front end” or the “CLI”. • configuration — A configuration is a description of a target architecture, and is loaded into Simics with the read-configuration command. Note that a configuration can also include the state of the target, and saved from within Simics using the write-configuration command, in which case it provides a portable checkpoint facility. • craff — Compressed Random Access File Format, used to save raw data for objects, such as disk dumps and target memory contents. A separate utility allows you to compress input data to Simics, such as target disk dumps, in a format that Simics can use directly. • cycle — The smallest unit of time in Simics. The cycle count is usually the same as the step count, except in Simics Out-Of-Order or when memory transactions are stalled. • device — A module modeling a hardware device that the target processor can access. 41

• event — A Simics event occurs at some predefined point of simulated time. Time can be specified either as a number of issued instructions on a simulated processor, or a number of simulated clock cycles. • extension — A module which is not a device, but adds features to Simics; e.g., a statistics collection module. • hap — Defined simulation or simulator state changes that may trigger callback functions. • host addresses — Logical memory addresses on the host machine; i.e., addresses in the virtual memory space that the simulator itself is running in. • host — The machine the simulator (Simics) is running on. • logical addresses — Memory addresses corresponding to virtual or logical addresses on the target machine. These are typically translated by a memory management unit (MMU) to physical addresses. • memory hierarchy — A user defined module that simulates caches and timing of memory operations. Interfaces to Simics using a memory transaction data structure. • module — A dynamically linked library or a script that interfaces to Simics and extends the functionality of the simulator. A module is either an extension or a device. • physical addresses — Memory addresses corresponding to physical/real addresses on the target machine; i.e., the actual address bits put out on the memory bus. • Python — An object oriented script language. See http://www.python.org for more info. • /host filesystem — A “magic” feature allowing simple accesses from a simulated system to the host’s real file system. It is called “hostfs” or “slash host” because the preconfigured dumps have a “/host” mount point for the magic device. This is presently only supported when running Solaris or Linux on the target machine. • STC — Simulator Translation Cache. A mechanism in the simulator to improve simulator performance. Among other things, it filters uninteresting memory accesses from the memory hierarchy. • step — An issued instruction that completes or causes an exception, or an external interrupt. • system level instruction set simulation — The effect of every single instruction is simulated both on user and supervisor level. At any instruction, the simulation can be stopped and state can be inspected (and changed). • target — The simulated machine.

42

Chapter 6

Startup Options This chapter describes the most important command-line options accepted by Simics. A complete description can be found in the reference manual. There are two ways of starting Simics. You can start it by simply running the binary file in the directory [simics]/host/bin where host corresponds to your computer, or by using a startup script simics that is present in each simulated machine directory. By using the script you can select a specific processor model without worrying about where the program files are, or their exact names. For example, if you want to run enterprise, an x86 machine, with a Pentium III, you will run a command similar to: joe@computer:[simics]/home/enterprise$ ./simics x86-p3 -x enterprise.simics

The simics script selects a default target (here x86-p2) if none is provided.

6.1

Processor Models

Here is a list of the different processor models that are provided by default with Simics. If a specific model is missing and you wish to use it, you can request it from Virtutech via the Simics Forum. Processor model Simics/SunFire sparc-u2 sparc-u2-o3 sparc-u2-ma Simics/Serengeti sparc-u3 sparc-u3-o3 sparc-u3-ma

Description UltraSPARC II UltraSPARC II (out-of-order mode—see chapter 16) UltraSPARC II (micro-architecture mode—see chapter 16) UltraSPARC III UltraSPARC III (out-of-order mode—see chapter 16) UltraSPARC III (micro-architecture mode—see chapter 16)

43

6.2. Common Options sparc-u3+ Simics/x86 x86-486sx x86-p2 x86-p2-stall x86-p3 x86-p4 x86-p4-stall Simics/x86-64 x86-hammer Simics/Alpha alpha-ev5 Simics/PPC ppc750 ppc7450 Simics/IA64 ia64-itanium ia64-itanium2 Simics/ARM armv5te Simics/MIPS mips-4kc

6.2

UltraSPARC IIIcu Intel 486SX (no hardware floating-point) Intel Pentium II Intel Pentium II (with memory stalling support—see chapter 16) Intel Pentium III Intel Pentium 4 Intel Pentium 4 (with memory stalling support—see chapter 16) AMD x86-64 Alpha 21164 PPC 750 PPC 7450 Intel Itanium Intel Itanium2 Generic ARMv5 MIPS 4Kc

Common Options

Here is a list of the most common options used when starting Simics: -c file Tells Simics to read a specific configuration file. This is equivalent to run the command read-configuration file after starting Simics. -central address:port Tells Simics to connect to a specific Simics Central instance. This option takes an IP address and an optional port number (the default is 4711). If no port number is supplied, and the local host’s address is supplied, Simics will try to connect to the default Unix file socket. -h Makes Simics print out a list of the possible startup flags along with a short description. -v Makes Simics print out its version number. -x file Tells Simics to run the script file.

44

Chapter 7

Usual Simics Commands This chapter contains a brief description of usual Simics commands. A complete list by categories is available in all the Simics Reference Manuals. The help command at the prompt also allows you to browse the commands’ documentation.

7.1

Simulation

At the Simics prompt, you can run the simulation with the continue (c) command, followed by the number of steps you want to run. If no argument is provided, the simulation will run until control-C is pressed in the Simics console. You can also use stepi (si) to make the simulation progress step by step. On out-oforder versions of Simics, you can use the step-cycle (sc) command to make the simulation progress cycle by cycle.

7.2 Simulation State All processors support the pregs command to show the state of the main registers. The argument -all will allow you to inspect all the registers instead of the usual working set. If the processor has floating-point registers, pfregs can be used to print them out. By default, the pregs command (and other commands dependent on the cpu) uses the current cpu scheduled by the simulation. You can change the current selected cpu by using the pselect command. This won’t affect the simulation scheduling. You can inspect and change the contents of a register by using the read/write-reg commands. Using % is equivalent to the read-reg command (i.e., %pc, %eax, ...). You can inspect and change the contents of the memory by using the commands get, x and set. To get statistics concerning the current cpu, you can use the ptime command. 45

7.3. Scripts

7.3

Scripts

Simics can load both Simics scripts (a file containing a list of acceptable commands for the Simics frontend) or Python script with the commands run-command-file and runpython-file. You can read more about Simics scripting in chapter 10.

7.4

Modules

Simics usually handles modules automatically when loading a configuration. You may however want to load a specific module by yourself (like the trace module) with the load-module command. The modules currently loaded are available through the listmodules command. If a module fails to be loaded, it will be listed by the list-failedmodules command, along with an explanation of the problem. You can use the -v argument to get the exact error message preventing the module from loading.

7.5

Command-Line Interface

Simics command-line interface uses GNU Readline, which means you can use the usual readline control sequences for history browsing and command-line editing. You can also tell the prompt to run commands every time a new command is issued with display command. To stop the command from being run, use undisplay number where number is the number written before the command output. The print command allows you to print out a value in different ways (binary, hexadecimal, etc.). The CLI also supports the following Unix shell-like commands: cd, date, dirs, echo, ls, popd, pushd, pwd.

46

Chapter 8

The Command Line Interface The Simics Command Line Interface (CLI) is an advanced text based user interface with builtin help system, context sensitive tab-completion, and scripting support (using Python).

8.1

Invoking Commands

Commands are invoked by typing them at the command line followed by their arguments. The synopsis part of a command documentation (see the Simics Reference Manual) explains how to call a command. Here are two examples: SYNOPSIS command1 -x -y -small [cpu-name] address (size|name) SYNOPSIS command2 files ... Arguments starting with a hyphen are flags and are always optional for a command. Flags can be more than one character long so it is not possible to write -xy for -x -y. The order of the flags is not significant and they can appear anywhere in the argument list. Arguments enclosed within square brackets are optional, thus it is not necessary to specify cpu-name in the example above. address,on the other hand, is required. The last argument to command1 is either a size or a name, but not both. Such arguments are called polyvalues and can be of different types. Size and name are called sub-arguments. If an argument is followed by tree dots as the file argument in command2 it indicates that the argument can be repeated one or more times. The type of the arguments, e.g., if they are integers or strings, should be evident from their names. For example size should be an integer and name a string if not documented otherwise. Integers are written as a sequence of digits beginning with an optional minus character for negative numbers. Hexadecimal numbers can be written by prefixing them with 47

8.1. Invoking Commands

0x, octal numbers with 0o, and binary numbers with with 0b. Strings are written as is or within double quotes if they contain spaces or begin with a non-letter. Here are some possible invocations of the commands above: simics> command1 -small cpu0 0x7fffc000 14 -y simics> command1 0x7fffc000 foo simics> command1 -x "Pentium 4" 0x7fffc000 -8 simics> command2 "/tmp/txt" "../bootdisk" floppy In the first example cpu-name is passed as the string cpu0 and size as the integer 14. In the second invocation cpu-name has been omitted and name is set to the string foo. The third example illustrated the use of a string containing a space. In all command1 examples the address is set to the hexadecimal value 0x7fffc000. command2 takes a list of at least 1 string. A few commonly used commands have aliases. Thus it is possible to write c for continue and si for step-instruction for example. Command aliases are documented with their corresponding command in the Simics Reference Manual.

8.1.1

How are Arguments Resolved?

Simics tries to match the arguments in the order that they appear in the synopsis. If the type of the next argument is the same as what is typed at the command line the argument will match. If there is a mismatch and the argument is optional the argument will be skipped and the next will be matched etc. If not optional, the interpreter will fail and explain what is expected. For polyvalues, the argument will be matched if one of its sub-arguments match. There are situations however when this method is not sufficient. For example, when two arguments both have the same type and are optional, there is no way to know which argument to match if only one is given. This is resolved by naming the arguments: argname=value. For example command1 in the example above can be invoked like this: simics> command1 size=32 -y address = 0xf000 -small cpu-name=cpu0

Thus there is no ambiguity in what is meant and in fact this is the only way to specify a polyvalue with sub-arguments of the same type. Note also that the named argument can be placed in any order. As stated in the previous section this holds for flags as well.

8.1.2

Namespace Commands

Configuration objects (such as devices or CPUs) that define user commands usually place them in a separate namespace. The namespace is the name of the object. Namespace commands are invoked by typing the name of the object, followed by a dot and the command name: object.command, e.g., 48

8.2. Help System

simics> cache0.print-status All namespace commands are listed in the Simics Reference Manual.

8.1.3

Expressions

The CLI allows expressions to be evaluated, for example: print -x 2*(0x3e + %g7) + %pc The precedence order of the operators is as follows (highest first): % $ ˜ pow *, / +, &, |, ˆ

get register value read Simics variable bitwise not power of multiplication, division addition, subtraction left, right shift bitwise and, or, xor

Parentheses can be used to override the priorities. Commands which return values can also be used in expressions if they are enclosed within parentheses: print -x (cpu0.read-reg g7) Values can be saved in variables for later use. You set a variable by simply giving an assignment command such as var = 15. The value of the variable can be read later with $var.

8.1.4

Interrupting Commands

Any command which causes the simulation to advance (i.e run) can be interrupted by typing control-C. The simulator will gracefully stop and prompt for a new command. If Simics hangs for some reason, possibly due to some internal error, you can usually force a return to the command line by pressing control-C twice or more times in a row. Note: Pressing control-C several times may damage some internal state in the simulator so should be used sparingly.

8.2

Help System

All Simics commands (which are documented in the Simics Reference Manual) are grouped together into categories. To list the categories type help at the command line. The list should look something like this: 49

8.2. Help System

simics> help List of command categories: FAS366U-commands MK48T08-commands Z8530-commands arithmetic-commands bitwise-commands breakpoint-commands change-commands command-line-commands configuration-commands

| | | | | | | | |

context-commands device-commands frontend-commands general-commands image-commands inspect-commands path-commands recorder-commands sbus-hme-commands

Note that since Simics configuration can change between sessions and even dynamically through loading modules the commands and command categories may look different. Type help category for a list of commands, e.g., help change-commands will list all commands belonging to that category: simics> help change-commands .load-binary .load-file .set .disable .enable .set-pc .write-reg load-binary load-file load-kernel pdisable penable set set-pc write-control-reg write-reg

-

load binary (executable) file into memory load file into memory set physical address to specified value switch processor off switch processor on set program counter write to register load binary (executable) file into memory load file into memory deprecated command switch processor off switch processor on set physical address to specified value set current processor’s program counter write to control register write to register

For further documentation of a command, type help command-name. Namespace commands appear in the form .command where name is the class name or interface name the command belongs to. This means that the command will work with all objects of the corresponding class or all objects that implements the corresponding interface. Use the command list-objects to list all objects and their corresponding classes and interfaces. To see the documentation for a namespace command type help object.command or help .command (angle brackets included), e.g., help cpu0.enable or help 50

8.3. Tab Completion .enable. The latter form is useful if there is no object created that defines a certain namespace command. To view all available commands for an object type help object. The help command recognizes commands (and categories) on minimal prefixes, i.e., just type as much of a command as is unique. If it is ambiguous, Simics will list the alternatives. Thus, typing help s will list all commands that begin with “s” (unless there is a command that is called “s” or has an alias “s”). help -all will list all commands and help help will print the documentation of the help command. The apropos command is useful to find a command for a specific task. Type apropos keyword to list all commands whose documentation contains the specified keyword.

8.3

Tab Completion

The command line interface has a tab-completion facility (if the readhist module has been loaded), that works not only on commands but on their arguments as well. The philosophy is that the user should be able to press the tab key when uncertain about what to type, and Simics should fill in the text or list alternatives. For example com will expand to the command beginning with com or list all commands with that prefix if there are several. Similarly, disassemble will display all arguments available for the command. In this case Simics will write: address =

count =

cpu-name =

to indicate that these alternatives for arguments exists. Typing disassemble cp will expand to disassemble cpu-name = and a further tab will fill in the name of the CPU that is defined (or list all of them).

8.4

Remote Frontend

Simics can be “remote-controlled” from another host. To enable this, issue the command enable-external-commands. simics> enable-external-commands [rf0] Listening for commands on port 4712

To specify another port, either give it as parameter to enable-external-commands, or use the command hremote-frontendi.set-port. If you wish to disable the local console such that only the remote console can issue commands, use the command hremotefrontendi.lock-console 1. To send commands to Simics from another host, the script remote-frontend is used. This script is located in the directory src/misc/remote-frontend. In the following example, Simics is run on the host isolde, and connected to from the host tristan. tristan$ ./remote-frontend -s isolde

51

8.4. Remote Frontend

Connected to Simics at isolde:4712. Simics Remote Frontend (Simics 1.2.0, Thu Mar

7 15:51:17 CET 2002)

Type ’rfhelp’ for info on remote-frontend specific commands. simics@isolde>

Note: The remote-frontend script assumes that there is a Python 2.x executable called python in the user’s $PATH. If this is not the case (the script will warn if not), execute the script with the Python 2.x executable explicitly: $ /path/to/python-2.x/bin/python ./remote-frontend Or, use the -python option to Simics: $ [...]/bin/simics-sparc-u3 -python ./remote-frontend

The remote-frontend script engine is very simple: commands are not interpreted in any way (except for the rf... commands described below) but passed verbatim to the Simics frontend script engine and executed there. The remote-frontend script accepts several parameters identically as Simics usually does. For example, the parameter -x file causes the frontend script to read commands from file. Type remote-frontend --help for a complete list of options. The remote-frontend script engine introduces a few commands for itself. These commands all begin with rf. Type rfhelp to get a list of all available remote-frontend specific commands. The important ones are listed below. rfinfo Print information about which Simics backend the frontend is connected to. rfquit Quit the frontend without quitting the Simics backend. rfconnect host:port Connect to a remote Simics. If the host and port are excluded, defaults will be used (local host, port 4712). This command enables the frontend to be connected to multiple Simics backends at the same time. rfselect num Select which Simics backend subsequent commands should apply to. num refers to the number printed using the rfinfo command. rfdisconnect Disconnect from the currently selected Simics backend. 52

8.4. Remote Frontend

rfbreak This command is similar to pressing control-C at the local Simics console. It instructs Simics to stop simulating and return to prompt. The option -b to the remotefrontend makes it perform an implicit rfbreak immediately after connecting. rfwait timeoutsecs Wait until Simics stops simulating and returns to prompt. This command is intended to be used after issuing commands like run 100000 to make sure the next command is not issued until Simics has completed the specified number of cycles. If timeoutsecs is specified, Simics will timeout after the specified number of seconds. The protocol used to communicate with Simics is described in the Reference Manual.

8.4.1

Remote Frontend Limitations

Multiline commands The remote-frontend protocol does not allow for multiline commands. For example, entering the string @def fun(): at the local console will cause Simics to print a secondary prompt and wait for further input (the rest of the function). If the string is entered in the remote-frontend, Simics will get a syntax error. Synchronous commands All commands in Simics are synchronous, i.e., Simics waits until the command has completed before returning to prompt. However, when entered from the remote frontend, some commands return immediately without waiting for Simics to complete them. Among these commands are continue, run, stepi, and other command which cause Simics to execute code. To wait until such a command has completed, use the rfwait command. These limitations may cause some Simics scripts to be unusable as remote-frontend scripts.

53

8.4. Remote Frontend

54

Chapter 9

Configuration and Checkpointing Configurations are descriptions of target systems, and are used to describe to Simics what the simulated machine looks like. Configuration files are written in a specialpurpose configuration language, and are usually named with a .conf suffix. The configuration language is designed to enable users to set up complex machine configurations with minimal effort, to simplify the understanding of machine specifications, and to support a simple form of portable checkpointing. A configuration consists of an unordered collection of objects. Objects can be connected to other objects by setting attributes in the configuration file. Below is an example of an object definition. Object definitions are always of the form OBJECT object-name TYPE class-name { attributes }. In this case we define an instance of the AM79C960 class (a 10Mbps ISA ethernet card with on-board DMA) named lance0. By setting the irq_dev and the irq_level attributes we connect the device to an interrupt target. Since this device has on-board DMA we also have to connect it to a memory space with the memory attribute. We also connect the device to a recorder which can record (and in later sessions play back) ethernet traffic. Finally, the queue attribute specifies which timing domain this object belongs to. OBJECT lance0 TYPE AM79C960 { irq_dev: isa0 irq_level: 7 memory: phys_mem0 recorder: rec0 queue: cpu0 } All the attributes in the example above are required attributes. The configuration system asserts that all such attributes are set when loading a configuration file. Most classes also have optional attributes that need not be in the configuration file, but which can be set to alter the behavior of the object. The lance0 definition only uses two types of attribute values, object names and (signed 64-bit) integers. The possible value types are: 55

string Strings are enclosed in double quotes, with C-style control characters: "a string\n" integer Integers can be in hexadecimal (0xfce2) or signed decimal (-17) notation. floating-point Specified in decimal (1.0e-2) or hexadecimal (0x5.a21p-32) style, just like in C. object The name of a configuration object: cpu0. list Comma-separated list of any attribute values, enclosed in parentheses. Example: ("a string", 4711, (1, 2, 3), cpu0) raw data Arbitrary data; typically used to save large dumps of binary information. The data itself is stored in an external file. The syntax is [R length-in-bytes filename file-offset]. To enable processors to access lance0, we have to map it to one or more spaces. AM79C960 is an ISA device, so we add it to a port-space. OBJECT port_mem0 TYPE port-space { map: ((0x40, pit0, 0, 0, 1), ... (0x300, (0x301, (0x302, (0x303, (0x304, (0x305, (0x30e, (0x30f, (0x310, (0x312, (0x314,

lance0, lance0, lance0, lance0, lance0, lance0, lance0, lance0, lance0, lance0, lance0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x0e, 0x0f, 0x10, 0x12, 0x14,

1), 1), 1), 1), 1), 1), 1), 1), 2), 2), 2),

... (0x3d5, vga0, 0, 0x3d5, 1)) } The map attribute in the port-space class takes a list of lists, each of the form (baseaddress, object, function, offset, length). Had this instead been a memory mapped device, we would have mapped it to a memory-space object (which has the same kind of map attribute as the port-space class). 56

9.1. Saving and Restoring Configurations The mapping of PCI devices to spaces is normally handled by the pci-device and pci-bus classes. The last link in the chain from the processor to the device is the connection between the processor and the space. OBJECT cpu0 TYPE x86 { queue: cpu0 freq_mhz: 20 physical_memory: phys_mem0 port_space: port_mem0 } Above we connect cpu0 to the port_mem0 I/O-space and the phys_mem0 memoryspace.

9.1

Saving and Restoring Configurations

Configurations are loaded into Simics with the read-configuration command. Note that the current version only supports exactly one read-configuration per session. The current configuration can be saved with the write-configuration command. The saved configuration includes all simulated state in a portable format, allowing you to use a single saved configurations on any host system. Note that saved configurations do not include most forms of statistics gathered during the simulation.

9.2

Modifying Saved Configurations

A configuration file saved with the write-configuration command is just like any other configuration file. This means that you can modify a saved configuration by editing the configuration file. However, modifying saved configurations requires some extra care. Adding or removing devices may confuse the operating system, which does not expect devices to appear or disappear while the system is running, and cause it to crash. Even changing the processor frequency may be enough to confuse the operating system.

9.3

Ready-to-run Configurations

Simics includes ready-to-run configurations for most of its targets. They are designed to work along the disk images distributed by Virtutech. Since Simics supports scripting through Python (see Chapter 10), most of the examples are not written directly as configuration files, but as scripts manipulating the configuration objects. This allows a greater flexibility in defining machines, and gives a better interface to users who want to change the machines’ description. The scripted 57

9.3. Ready-to-run Configurations configuration system is described in the Target Guides corresponding to each Simics target. Note: At any time, you can obtain an equivalent configuration file by starting Simics from a configuration script and then running the write-configuration command at the Simics prompt. Note that Virtutech only distributes images of freely available operating systems. If you wish to run a system with license restrictions, you have to install it by yourself on the simulated machine. The Target Guides provide information on how to perform usual installations.

58

Chapter 10

Script Support in Simics Simics provides support for the script language Python (http://www.python.org). By using Python the user can extend Simics, and control it in greater detail. Python can interface with Simics using functions in the Simics API.

10.1 Python in Simics Python is normally hidden from the user by the command line interface (CLI). But since CLI is implemented in Python, it also provides simple access to the Python environment, making it easy to write your own functions and scripts. Note: All commands in Simics are implemented as Python functions and the source is available in the distribution. To execute some Python code from the command line, the @ character is used to prefix the line. Example: simics> @print "This is a Python line" This is a Python line simics> For code spanning more than one line, the prompt will change to ....... and more code can be inserted until an empty line is entered. The full code block will then be executed. Example: simics> @if SIM_number_processors() > 1: ....... print "Wow, an MP system!" ....... else: ....... print "Only single pro :-(" ....... 59

10.2. Accessing the Configuration from Python

Wow, an MP system! simics> Entering more than one line is useful for defining python functions. It is also possible to execute Python code from a file, which is done with the run-python-file command. If the Python code is an expression that should return a value to the CLI, the python command can be used, or the expression can be back-quoted. The following example selects a file with Python commands to execute depending on the number of processors in the system: simics> run-python-file ‘"abc-%d.py" % SIM_number_processors()‘ If the system has 2 processors, the file abc-2.py will be executed.

10.2

Accessing the Configuration from Python

10.2.1

Configuration Objects

All configuration objects are visible as objects in Python. The global Python module conf holds all such objects. Attribute values can be both read and written using attributes in Python. Example: (print the pci_devices attribute in a pci-bus object) simics> @print conf.pcibus25B.pci_devices [[2, 0, ’glm0’]] Any ’-’ (dash) character in the object name, or in an attribute name, is replaced by ’_’ (underscore). Indexed attributes can be accesses using [...] indexing in Python. It is also possible to index other list attributes this way, but it is inefficient since the full list is converted to a Python list before the element is extracted. Here are some examples of indexed attributes access: simics> @print conf.sb0.scsi_phases[1] Arbitration simics> @print conf.phys_mem0.memory[0x100000:0x10000f] (157, 227, 191, 80, 3, 0, 0, 0, 130, 16, 96, 0, 131, 40, 112) simics> @conf.phys_mem0.memory[0x100000:0x100003] = (100,101,102)

60

10.2. Accessing the Configuration from Python

Warning: Python only supports 32 bit integers in keys when doing sliced indexing (no bignums). However, the Simics API treats [m:n] synonymous to [ [m, n-1] ], so instead of conf.phys_mem0.memory[0x1fff80082f0L:0x1fff80082f8L] (which won’t work), write conf.phys_mem0.memory[[0x1fff80082f0L,0x1fff80082f7L]]

10.2.2

Creating Configurations in Python

In addition to using .conf files, it is also possible to create and load configurations from Python. The main advantage is that the configuration can be parameterized without the need of multiple .conf files. A part of a configuration in Python may look like: from configuration import * config += ([OBJECT("sd" + tgt_name, "scsi-disk", image = "sd" + tgt_name + "_image", scsi_bus = "sb" + tgt_name, scsi_target = scsi_target, queue = "cpu0", geometry = geometry)] + [OBJECT("sd" + tgt_name + "_image", "image", size = geometry[0] * geometry[1] * geometry[2] * 512, queue = "cpu0")])

This will create one scsi-disk, and one image object with names based on the tgt_ name variable. The scsi_target and geometry variables specifies the scsi-disk in more detail. Note: The variable holding the list of objects and attributes can have any name. In this example config is used. When all objects has been added to the config list, this configuration can be loaded into Simics with: SIM_set_configuration(config) The configuration namespace also defines some functions that simplifies the access to the config list in Python. These functions can only be used before the configuration is loaded into Simics. get_attribute(config, objname, attrname) Returned the value of an attribute for object objname in config. set_attribute(config, objname, attrname, new_value) Set the value of an attribute for object objname in config. 61

10.3. Accessing Commmand-Line Commands from Python object_exists(config, objname) Check if the named object exists in config. write_configuration(config, file) Write all objects and attributes in config to a .conf file. rename_object(config, old_name, new_name) Change the name of an object in config. delete_object(config, objname) Delete an object from config. Most configurations supplied with Simics are Python based. However, the way that configurations are created differs between targets. Refer to the corresponding Simics Target Guide for more information. Python files that are used to create configurations can be found in the [simics]/home/scripts directory, and, to some extent, in each target machine directory.

10.3

Accessing Commmand-Line Commands from Python

At times, it can be useful to access command-line commands from a Python script file. This is done using the eval_cli_line(cli_string) function, which takes a string which is then evaluated by the command-line front-end. For example, write eval_cli_line("pregs") to execute the pregs command.

10.4

Script Branches

10.4.1

Introduction to Script Branches

Script Branches allow the user to write Python scripts that can wait for Simics haps at anytime without breaking the sequential flow of the code. This is typically used to avoid breaking a script into many small sections, each installed as a hap callback. A simple example from a Simics script: @def testA(): print ret = print print

"This is a test - going to sleep" wait_for_hap_idx("Core_Step_Count", 10) "Woke up we got the following return: %d" % ret "Leaving branch"

@start_branch(testA) The example above will execute the first print statement and then go to sleep waiting for the Step_Count hap. When Simics has executed (a total number of) 10 instructions, the branch will wake up and run the following two print statements. 62

10.4. Script Branches

10.4.2

How Script Branches Work

When a script branch is started (using start_branch()), it begins executing immediately, and runs until a wait_for_hap() call is performed. Execution is then resumed in the main script; i.e., there is never any concurrent activity. When a hap occurs that a script branch is waiting for, the branch continues executing once the currently simulated instruction is ready. To aid debugging, some information can be printed each time a branch is started, stopped, suspended or resumed. This is enabled by setting the branch-info attribute in the python object to 1. Example: simics> @conf.python.branch_info = 1 Note: Since only one branch can be active at once, any callback to Python from Simics will execute in the currently active branch. I.e. if a branch installs a callback it is most likely that it will be called when the main Python branch is active.

10.4.3

Script Branch Functions

The following is a list of Python functions that implement the user interface to script branches. wait_for_hap(hap_name) Pause branch waiting for a hap to occur. wait_for_hap_idx(hap_name, idx) Same as previous but use indexed hap. wait_for_hap_range(hap_name, low, high) Same as previous but use a range for the indexed hap. start_branch(branch_name) Create a new script branch and start it.

10.4.4

Script Branch Limitations

There are still several limitation that apply to script branches. The first three in the list are enforced by Simics: • Similar to other callbacks, such as event handlers and hap callbacks, the script branch may not try to advance the simulation. • Script branches may not start new branches. • The main branch may not call the wait_for_hap...() functions. • Breaking the simulation with multiple control-C (that forces Simics back to prompt) may confuse the Python interpreter about what thread is active. But since the simulation usually don’t survive this anyway it is not a major problem.

63

10.4. Script Branches

64

Chapter 11

Simics Programming Interface 11.1

The Simics API

The Simics API is a set of functions that provide access to Simics functionality from loadable modules (i.e., devices and extensions), and Python scripts. All functions in the Simics API have a name that starts with “SIM_”. They are described in details in the Simics Reference Manual. By using the api-help and api-apropos commands you can get the declarations for API functions and data types. api-help identifier will print the declaration of identifier. api-apropos identifier lists all declarations where identifier appears. The Simics API functions are available in the sim_core and sim_processor Python modules. These two modules are imported into the Python environment in the frontend when Simics starts; for user written .py files however, the modules must be imported explicitly, i.e., from sim_core import * from sim_processor import * Errors in API functions are reported back to the caller using frontend exceptions. The exception is thrown together with a string that describes the problem more in detail. Examples of exceptions are General, Memory, Index, IOError... For the Python environment, Simics defines an exception subclass for each of its defined exceptions in the sim_core module. These are raised to indicate exceptions inside the API functions. When errors occur in the interface between Python and the underlying C API function, the standard Python exceptions are used; e.g., if the C API function requires an int argument, and the Python function is called with a tuple, a Python TypeError exception is raised. 65

11.2. Haps (Event Occurrences)

11.2

Haps (Event Occurrences)

11.2.1

Haps Description

A hap is an event or occurrence in Simics with some specific semantic meaning, either related to the target or to the internals of the simulator. Examples of simulation haps are: • Exception or interrupt • Control register read or write • Triggered breakpoint • Execution of a magic instruction (see below) • Device access There are also haps which are related to the simulator, e.g., (re)starting the simulation or stopping it and returning to prompt. Note: In Simics documentation, the word “event” is used exclusively for events that occur at a specific point in simulated time, and “hap” for those that happen in response of other specific conditions. Callback functions from any supported language can be tied to a certain hap. The callback can be invoked for all occurrences of the hap, or for a specified range. This range can be a register number, an address, or an exception number, depending on the hap. A complete reference of the haps available in Simics can be found in the Simics Reference Manual.

11.2.2

Example of Python Callback on a Hap

This example uses functions from the Simics API to install a callback on the hap that occurs when a control register is written. The SIM_hap_register_callback_idx() function sets the index of the control register to listen to, in this case the %pil register in a SPARCV9 processor. @pil_reg_no = SIM_get_control_register_number(conf.cpu0, "pil") # print the old and new value when %pil is changed @def ctrl_write_pil(dummy, cpu, reg, val): print "Write to %%pil. 0x%x -> 0x%x" % ( SIM_read_control_register(cpu, pil_reg_no), val) # install the callback @SIM_hap_register_callback_idx("Core_Control_Register_Write", ctrl_write_pil, pil_reg_no, 0)

66

11.2. Haps (Event Occurrences)

11.2.3

Magic Instructions

For each simulated processor architecture, a special instruction encoding has been chosen to be a magic instruction for the simulator: when this instruction is executed, the hap Core_Magic_Instruction is triggered. It can be used to help scripting the simulated machine’s behaviour, for example by starting or shutting down statistics gathering when a magic instruction is encountered. These instructions have no effect on the simulated system so that they have very little impact on the simulation, and none on the program behaviour. This also means that they also have no effect when the program is run on actual hardware. Magic instructions are defined and available in simics-magic-instructions.h, which can be found in the [simics]/host/obj/include/ directory. In most cases, it is possible to pass a numeric parameter along with the magic instruction.

Target Alpha ARM IA-64 MIPS PowerPC SPARC x86

Magic instruction binary: 0x70000000 orreq r0, r0, r0 nop (0x100000 + n) li %zero,n fmr n, n sethi (n), %g0 xchg %bx, %bx

Conditions on n n=0 n=0 0 6 n < 0x100000 0 6 n < 0x10000 0 6 n < 32 1 6 n < 0x400000 n=0

Figure 11.1: Magic instructions for different Simics Targets A magic breakpoint is a special form of magic instruction that interacts with the magic-break-enable/-disable commands. When magic breakpoints are enabled, if the argument matches the condition n == 0 || (n & 0x3f0000) == 0x40000 the simulation is stopped automatically. The simics-magic-instructions.h file defines two macros, MAGIC(n) and MAGIC_BREAKPOINT, that can be use in the source code of the simulated program. Note: The declaration of the macros are heavily dependant on the compiler used, so you may get an error message telling you that your compiler is not supported. You will need to write by yourself the inline assembly corresponding to the magic instruction you want to use. The GCC compiler should be always supported. Here is a simple pseudo-code example: #include "simics-magic-instruction.h" int main(int argc, char **argv) 67

11.2. Haps (Event Occurrences)

{ initialize(); MAGIC(1);

tell the simulator to start the cache simulation

do_something_important(); MAGIC(2);

tell the simulator to stop the cache simulation

clean_up(); } This code needs to be coupled with a callback registered on the magic instruction hap to handle what happens when the simulator encounters a magic instruction with the arguments 1 or 2 (in this example, to start and stop the cache simulation).

68

Chapter 12

Managing Disks, Floppies, and CD-ROMs In order to use Simics you must have a disk dump with the operating system and other programs installed. Some disk dumps are provided by Virtutech for freely available operating systems (see section 2.5). If you want to run another operating system on Simics, install more programs on the disk, or import source files, there are several ways to accomplish this: • You can install a new OS along with new programs on a real machine and create an image from the hard disk. See section 12.2. • You can modify the disk image file directly via a loopback device. See section 12.8. • Using Simics: – You can install files using the simulated CD-ROM by linking it to a real CDROM drive on your host machine, or by using a CD image file. See sections 12.4 and 12.5. – You can copy files from the simulated floppy drive by linking it to the real host floppy device, or by using a floppy image file. See sections 12.6 and 12.7. – You can use the /host filesystem to directly access your real filesystems from the simulated machine. See section 12.9. – You can download files over the simulated network. See chapter 14. The following chapters will go into details about these different methods.

12.1

Saving Modifications to Simulated Disk

If you choose to install something from within Simics you should remember that by default the disk image is read-only. This means that any alterations made to the disk 69

12.1. Saving Modifications to Simulated Disk when running Simics are not written to the disk but instead saved in memory only. This is preferred since it allows you to rerun Simics with the exact same behavior each time and you cannot damage the original disk, even when you are super-user on the virtual system. It also allows you to run multiple instances of Simics and reuse the same disk dump. To save your newly installed programs, you have the following options: • Take a checkpoint (with write-configuration). • Change the attribute on the disk image object to read/write. • Save diff files which can be loaded together with the orginal disk. • Write out a completely new disk image from within Simics.

Note: Remember that the target OS might have cached disk contents in memory. In order to have a clean disk, which can be used at boot, you should sync the disk, for example by running init 0 on a unix target system, or shutting down the operating system, before you stop the simulation. (This is not necessary if you take a checkpoint, but then you will always need to start from that checkpoint.)

12.1.1 Using Read/Write Disks To make the disk read/write, simply set the second parameter (the “read-only” flag) of the files attribute in the disk image object to “rw”. Read-only disk in a Python scripted file: files = [["hippie3-rh62.craff", "ro", 0, 1056964608, 0]] Read-only disk in a .conf file: files: (("hippie3-rh62.craff", "ro", 0, 1056964608, 0)) Read-write disk in a Python scripted file: files = [["hippie3-rh62.craff", "rw", 0, 1056964608, 0]] Read-write disk in a .conf file: files: (("hippie3-rh62.craff", "rw", 0, 1056964608, 0)) Using read-write files is preferable when making large alterations to the disk since you might otherwise run out of memory on your host. Another way to avoid using too much host memory is to use the limit-memory command in the image class. 70

12.1. Saving Modifications to Simulated Disk

Note: Use this feature with caution. Make sure to take a copy of the original disk image before running Simics with the image in read/write mode. Remember to sync the disk within the target OS before exiting Simics.

12.1.2

Saving a Disk Diff

If you make smaller changes and perhaps want to keep one disk as reference and have multiple combinations of disk contents it is better to save disk diffs. This is how this can be achieved: simics> disk0.save-diff-file hippie-diff1.craff [disk0_image] Opened subfile ’hippie-diff1.craff’ (format craff) Saved the diff file as ’hippie-diff1.craff’ A new file called hippie-diff1.craff will then be created (in craff format) which contains the changes made to the disk. For Simics to use the disk together with the written changes you must either update the files attribute for the disk image object, or use the add-diff-file command. Adding diff file in a Python scripted file: files = [["hippie3-rh62.craff", "ro", 0, 1056964608, 0], ["hippie-diff1.craff", "ro", 0, 1056964608, 0]] Adding diff file in a .conf file: files: (("hippie3-rh62.craff", "ro", 0, 1056964608, 0), ("hippie-diff1.craff", "ro", 0, 1056964608, 0)) If the add-diff-file command is used it must be issued before the simulation is started, or the changes may not be noticed by the simulated system. simics> disk0.add-diff-file hippie-diff1.craff [disk0_image] Closed craff file ’hippie3-rh62.craff’. [disk0_image] Opened subfile ’../../import/x86/hippie3-rh62.craff’ (format craff) [disk0_image] Opened subfile ’hippie-diff1.craff’ (format craff)

Disk diffs are only generated from Simics, and their nominal size will always be as large as the entire disk (as can be seen in the examples above). To create a disk from several distinct disk dumps, you should not use the add-diff-file, but the process given in section 12.3 below. 71

12.2. Copying Real Disks

12.1.3

Writing Binary Data from Simics

Using an image object’s save command, you can save parts of, or a complete copy of that image’s binary data to a file. The syntax for doing that is: simics> disk_image0.save my-disk-dump.bin This will save a copy of all the data in the disk0_image to the my-disk-dump.bin file. You can also optionally specify a starting offset and a byte count: simics> disk_image0.save my-disk-sector.bin 0x10000 4096 This will save the 4KB of data starting at offset 0x10000. Note that this command can be used for memory as well, since memory and disks share the common image class to store their data. Note: The amount of data saved by [image].save can be significant, since it is not compressed in any way. Every byte on a disk will be saved to file, not just the space actually in use. For example, a disk with a size of 20 GB will generate a file of 20 GB, even if only 20 MB of it is being used. Saving disk diffs and combining them with the craff utility is recommended.

12.2

Copying Real Disks

It is possible to create a disk image by copying data from a real disk. If the disk that is to be copied contains an operating system, you must have at least two operating systems on the machine, since the partition that should be copied must not be in use or mounted. Before making a copy of a disk, some information about the disk should be gathered: • The number of disk cylinders • The number of sectors per track • The number of disk heads • The offset where the specific partition starts (optional) • The size of a specific partition (optional) On Linux and Solaris, these numbers can be fetched using the fdisk utility. On Windows, you can use the System Information application to find the information under Components/Storage/Disks. You have to select the Advanced setting from the View menu. You can choose to make a copy of the whole disk or just a partition from the disk. On Unix hosts, use the dd utility. Examples: 72

12.2. Copying Real Disks

dd if=/dev/hda2 of=hda2_partion.img dd if=/dev/hdb of=hdb_disk.img Windows-users who have the Cygwin toolset (http://www.cygwin.com) installed can use dd as described above, provided that the correct entries in the /dev filesystem are created. To access /dev/hda: mkdir -p /dev/hda mount -s -b ’\\.\PHYSICALDRIVE0’ /dev/hda You can also mount a specific drive-letter: mkdir -p /dev/fd0 mount -s -b ’\\.\A:’ /dev/fd0 or mkdir -p /dev/hda1 mount -s -b ’\\.\C:’ /dev/hda1 Then, use dd as described for Unix hosts. dd if=/dev/hda of=hda.img Cygwin’s mount program creates persistent mounts (they are stored in the registry), so you will only need to set these things up once. The -b option to mount ensures that no CR/LF conversions are made. Refer to the Cygwin documentation for further details on how to use the mount command. On Windows hosts without Cygwin, it is necessary to obtain some third-party program to create disk images. Note: To save space the disk image may now be compressed using the Simics craff utility. See section 12.10. The next step is to prepare the target configuration so it can use the new disk. For example edit the [simics]/home/hippie/hippie-common.simics file (x86). @add_isa_ide_disk(controller = 0, slot = "master", size = 1056964608, geometry = [2048, 16, 63], files = [["hda2_partition.img", "ro", 52641792, 618799104, 0]])

or: @add_isa_ide_disk(controller = 0, slot = "master",

73

12.3. Constructing a Disk from Multiple Files

size = 1056964608, geometry = [2048, 16, 63], files = [["hdb_disk.img", "ro", 0, 1056964608, 0]])

Similar for a SCSI disk (a SCSI controller must already exist): @add_scsi_disk(pci_bus_id = "0", slot_no = 2, scsi_target = 0, geometry = [2048, 16, 63], files = [["hdb_disk.img", "ro", 0, 1056964608, 0]])

Make sure to set the correct size argument to reflect the size of the disk that has been copied. If only a partition has been copied, we need to supply the address the partition starts on (in the first example, 52641792, in the other examples, 0) and the size of the partition (in the first example, 618799104). If the whole disk has been copied, the offset is zero and the size should be the size of the whole disk. For an x86 architecture the add_isa_ide_disk function will automatically set the BIOS geometry for both the C: and D: disks. It can also be set manually using the following command: rtc0.cmos-hd C 1023 16 63

12.3

Constructing a Disk from Multiple Files

In some cases, you may want to populate a simulated disk from multiple files covering different parts of the disk. For example, the partition table and boot sectors could be stored in a different disk image file than the main contents of the disk. In this case, you cannot use the add-diff-file command, but instead must use the files argument for the disk to put each image file at its appropriate location. Assume you are simulating a PC and want to build a disk from a main file called hda1_partition.img and a master boot record image file called MBR.img. The main partition will start at offset 32256 of the disk, and the MBR covers the first 512 bytes of the disk (typically, you would get the contents of these image files from the real disk as detailed in section 12.2). The following command in the simics start-up script will build the disk from these two files. @add_isa_ide_disk(controller = 0, slot = "master", size = 2559836160, geometry = [4960, 16, 63], files =[["hda1_partition.img", "ro", 32256, 1032151040, 0], ["MBR.img", "ro", 0, 512, 0]]) Note that the two image files cover non-overlapping sections of the disk. 74

12.4. Accessing Host CD-ROM

12.4

Accessing Host CD-ROM

Accessing the CD-ROM of the host machine from inside the simulation is supported on Linux and Solaris hosts. This is done by creating a host-cdrom object using the newhost-cdrom command. First, you should insert the CD in the host machine and figure out which device name it uses. On a Linux host, this is typically /dev/cdrom, which is a symbolic link to the actual CD-ROM device, e.g., /dev/hdc. Note that you need read/write access to the CD-ROM device for this to work. On a Solaris host, you need to specify the raw disk device, which can be found by using the mount command. The line that shows where the CD is mounted will look something like: /cdrom/mydisk on /vol/dev/dsk/c0t2d0/mydisk read only/nosuid on Fri Jul 26 11:52:52 2002

This means that the corresponding raw disk device will be called /vol/dev/rdsk/ c0t2d0/mydisk. Note the rdsk instead of dsk. When you have the correct device file name, you create a host-cdrom object and insert it into the simulated CD-ROM drive: simics> load-module host-cdrom Module host-cdrom loaded simics> new-host-cdrom /dev/cdrom host-cd0 cdrom ’host-cd0’ created simics> cd0.insert host-cd0 Inserting media ’host-cd0’ into CDROM drive Note that you must replace /dev/cdrom with the correct host device name as mentioned above, and cd0 with the correct Simics object name. Use the list-namespaces command to find the correct object of class scsi-cdrom or ide-cdrom. The cd0.insert command simulates inserting a new disk into the CD-ROM drive, and there is also a corresponding cd0.eject command that simulates ejecting the disk.

12.5

Accessing CD-ROM Image File

A file containing an ISO-9660 image can be used as medium in the simulated CD-ROM. This image file can be created from real CD-ROM disks, or from collections of files on any disk. An image can be created from a set of files with the mkisofs program, which is available on both Linux and Solaris. For example: mkisofs -l -L -o image -r dir

75

12.6. Accessing Host Floppy

Once you have an image file, a file-cdrom object can be created, and then inserted into a simulated CD-ROM device in the same way as above: simics> load-module file-cdrom Module file-cdrom loaded simics> new-file-cdrom myimage.iso cdrom ’myimage’ created simics> cd0.insert myimage Inserting media ’myimage’ into CDROM drive Note that cd0 above refers to the Simics object name of the CD-ROM drive. This may, or may not be called cd0. To see which object name to use, try the list-namespaces command and look for an object of class scsi-cdrom or ide-cdrom.

12.6

Accessing Host Floppy

It is possible to access a floppy on the host machine from within Simics if the host is running Linux or Solaris. For example (assuming the floppy device is called flp0): simics> flp0.insert-floppy A /dev/fd0 To boot directly from the floppy on a simulated x86 architecture you need to select the “A” drive to be the boot device (in, for example, hippie-generic.simics): simics> rtc0.cmos-boot-dev A

12.7

Accessing Floppy Image File

Sometimes it can be convenient to have copies of boot floppies as image files. To create an image of a floppy you can use the Unix command dd: dd if=/dev/fd0 of=floppy.img It is then possible to use this image file in Simics: simics> flp0.insert-floppy A floppy.img To boot directly from the floppy on a simulated x86 architecture you need to select the “A” drive to be the boot device (in, for example, hippie-generic.simics): simics> rtc0.cmos-boot-dev A

76

12.8. Accessing Disk Images from the Host Machine

12.8

Accessing Disk Images from the Host Machine

If the host OS supports loopback devices, which Linux and Solaris do, you can mount a disk image and get direct read/write access to the files within the disk. If you have root permissions this allows you to easily and quickly install files to the disk. Note: Remember that the disk file must be in “raw” format. Disk dumps supplied by Virtutech are normally in craff format (to save space) but you can use the craff utility to unpack the disk image to a raw disk image again. The resulting disk image files have the same size as the simulated disk, so you need to have sufficient free space on your disk to contain the entire simulated disk.

Note: Do not try to loopback mount a disk over NFS. This does not work reliably on all operating systems (Linux, for example). Instead, move the image file to a local disk and loopback mount it there. Solaris 8 example: lofiadm -a disk_dump /dev/lofi/1 mount /dev/lofi/1 mnt-point ... umount mnt-point lofiadm -d /dev/lofi/1

Linux example: mount mnt_pnt -o loop=/dev/loopn,offset=m

for example: # mount /disk1/rh6.2-kde-ws /mnt/loop -o loop=/dev/loop0,offset=17063424 # cd /mnt/loop # ls bin dev home lost+found opt root tmp var boot etc lib mnt proc sbin usr #

As shown in the example, the disk dump containing Red Hat 6.2 KDE WS is mounted on the /mnt/loop directory. The file system mounted on / starts on the offset 17063424 on the disk. Default in Linux is the ext2 filesystem. If you want to access another file system use the -t fs option to the mount command. Once the file system is mounted you now have free access to copy files into the file system or move interesting files out of the simulated disk. The offset can be calculated by examining the partition table with fdisk (from within Simics). Use mount to find the partition you want to edit or examine (e.g., /dev/hda2 is mounted on /usr which you want to modify). Next, run fdisk on the device handling this partition (such as fdisk /dev/hda). From within fdisk, change the display unit to sectors instead of cylinders with the u command and print the partition 77

12.9. Using the /host Filesystem

table with p. You will now see the start and end sectors of the partions, you can get the offset by taking the start sector multiplied with the sector size (512). When you have finished examining or modifying the disk, unmount it and touch the disk file. For example: cd umount /mnt/loop touch /disk1/rh6.2-kde-ws

The modification date of the disk file does not change when if you modify the disk via the loopback device. Thus, if you have run Simics on the disk file earlier, the OS might have cached disk pages from the now modified disk file in RAM. This would cause a new Simics session to still use the old disk pages instead of the newly modified pages. Touching the disk file should ensure that the OS rereads each page.

12.9

Using the /host Filesystem

The /host filesystem gives you access to the filesystem of your real computer inside the simulated machine. This simplifies greatly the process of importing files into the simulated machine. The /host filesystem is supported for targets running Solaris 7 to 9, and Linux kernel versions 2.0 through 2.4. The /host filesystem is installed on disk dumps distributed by Virtutech. For users booting from other disks, there are a number of steps needed to configure the target system. This process is target OS specific, and is described in the following sections. Note that you shouldn’t take checkpoints while hostfs is mounted inside your simulated machine, since the simulated operating system could have files opened in /host which won’t be available when the checkpoint is loaded next time. The /host filesystem is not a fully functional filesystem for all host/target combinations. It is recommanded to use it only to copy files to and from the simulated machine. The following limitations apply: Simulated OS Linux Solaris Windows

12.9.1

Limitations /host is read-only. Truncating files does not work. /host is not available currently.

Installing the /host Filesystem on a Simulated Solaris

These are the steps needed to install the /host filesystem on a simulated Solaris, versions 7, 8 or 9. When the instructions ask you to copy files into the simulated machine, one of the methods described above must be used (network, loopback disk access, cdrom...) • Copy the file [simics]/import/sun4u/mount_hostfs-solversion (where version matches the version of Solaris running on your simulated machine to /usr/ lib/fs/hostfs/ on the simulated disk, and rename it to mount. 78

12.10. The Craff Utility • Copy the file [simics]/import/sun4u/hostfs-solversion (with version as above) to /usr/kernel/fs/sparcv9/ on the simulated machine. • Copy the file [simics]/import/arch/hostfs-linux-version.o to the directory /lib/modules/version/fs/ on the simulated machine and rename it to hostfs.o. version should be the simulated machine’s kernel version. • If the pre-compiled hostfs module does not match the kernel you want to run on the simulated machine, you can download the hostfs source code from ftp:// ftp.simics.net/simicsfs/simicsfs.tar.gz. The README file in the archive will explain you how to insert the simicsfs module in the Linux kernel tree and compile it with the kernel you want to use. • Add the following line in the simulated machine’s /etc/fstab (replace /host with your mountpoint): special

/host

hostfs

noauto,ro

0 0

• Create the mount point on the simulated machine with mkdir /host. • For python based configurations (like enterprise), hostfs is already configured on Simics side. • If you’re writing your own configuration, you need to add a pseudo device of type hostfs to the machine configuration file and insert it into the physical memory space at the right place. The easiest way to do that is to look at a checkpoint from a pre-configured machine (like enterprise). • Mount the /host filesystem with the command mount /host on the simulated machine. The /host filesystem should now be working, and by issuing ls /host on the simulated machine, you should get a listing of the host machine’s files.

12.10

The Craff Utility

Most of the disk images distributed by Virtutech are in the craff file format. The craff utility can convert files into the craff file format, and also unpack files into the more familiar standard (linear) file format. In your Simics distribution you will find craff in platform_dir/bin (for example x86-linux/bin). The examples below assume that craff is present in your shell path. • Uncompress (-d) a single craff file to a raw file. joe@computer:˜$ craff -d -o hippie1.image hippie1-rh62.craff

• Compress (default) a single raw file into a craff file. joe@computer:˜$ craff -o image.craff image.raw

79

12.10. The Craff Utility • Merging multiple checkpoint files into a single file with zlib compression. Files specified later on the command line override earlier files. You will typically want to use the same parameters that Simics’ image class use to save data (-b 4096 -s 512 -i 1024). Note that all files but the last one need to be specified with the -f option. The -c 2 option is for zlib compression. joe@computer:˜$ craff -o merge.craff -b 4096 -s 512 -i 1024 -c 2 -f chkpnt1.craff -f chkpnt2.craff chkpnt3.craff

Craff can handle any combination of normal and craff files in both compress (default) and uncompress (-d) mode. • Create a single raw file based on one raw disk image and one checkpoint file. The craff utility always creates a raw file when in uncompress mode (with the -d switch). joe@computer:˜$ craff -d -o out.raw -f image.raw chkpnt.craff

• Create a craff file from one raw disk image and one checkpoint file. joe@computer:˜$ craff -o out.craff -b 4096 -s 512 -i 1024 -c 2 -f image.raw chkpnt.craff

See the reference manual for a complete list of craff utility options.

80

Chapter 13

Debugging Tools 13.1

Breakpoints

Like an ordinary debugger, Simics can run user binaries, allowing the user to set breakpoints, inspect state, single step, etc. Some difficult bugs are easier to find using various esoteric breakpoint types. In Simics you can set breakpoints on: • memory accesses: any range and combination of read/write/execute • time (number of cycles or instructions executed) • instruction types, such as control register accesses • device accesses Simics is fully deterministic, allowing you to narrow down the location of difficult bugs. If your session has interactive input, record the interactive input using the recorder functionality.

13.1.1

Memory Breakpoints

A memory breakpoint makes the simulation stop whenever a memory location in a specified address interval is accessed. The address interval can be of arbitrary length and the type of the memory access can be specified as any combination of read, write, and execute. As memory breakpoints refer to addresses within a memory space, the breakpoint itself is always connected to a specific memory space object in Simics. If this object is known by name (as phys_mem0 in this example), the breakpoint can be set with the break command: simics> phys_mem0.break address = 0x10000 length = 16 -w Breakpoint 1 set on address 0x10000, length 16 with access mode ’w’

81

13.1. Breakpoints

We can also use the break command without explicitly specifying an address space object. In this case the breakpoint refers to the memory space object connected to the current frontend processor (as specified with the pselect command): simics> break 0x20000 -x Breakpoint 2 set on address 0x20000 with access mode ’x’

13.1.2 Temporal Breakpoints Unlike an ordinary debugger, Simics can handle temporal breakpoints; i.e., breakpoints in time. As the concept of time is based on steps and cycles, a temporal breakpoint refers to either a step or a cycle of a processor object: simics> cpu0.cycle-break 100 simics> cpu0.step-break 100

In the example above, the breakpoints are specified relative to the current time. It is also possible to set temporal breakpoints in absolute time (note that it is impossible to set breakpoints in past time): simics> cpu0.cycle-break-absolute 100 simics> cpu0.step-break-absolute 100

13.1.3

Control Register Breakpoints

A control register breakpoint is triggered when a specified control register is accessed. The control register is specified with either name or number, and the type of access can be specified with any combination of read or write. For example: simics> break-cr reg-name = asi -w

Note that the exact nature of this command (as well as actual control register names) depends on the target architecture. See the documentation for break-cr in the Simics Reference Manual.

13.1.4

I/O Breakpoints

An I/O breakpoint is always connected to a specific device object in Simics, and the breakpoint is triggered when that device is accessed. The breakpoint is set using the iobreak command, and it assumes that we know the device object by name. We can also specify a number of access to ignore before the breakpoint is activated. For example; in order to break on accesses to the hme0 device, ignoring the first 100 accesses, we would use the following syntax: simics> io-break object-name = hme0 count = 100

82

13.2. Using GDB with Simics

Will break on I/O for device hme0, after 100 accesses

13.2

Using GDB with Simics

This chapter describes how to use the gdb-remote which lets you connect a GDB session running on your host machine to the simulated machine using GDB’s remote debugging protocol and use it to debug software running on the target machine. If you load the gdb-remote module in Simics, you can use the remote debugging feature of GDB, the GNU debugger, to connect one or more GDB processes to Simics over TCP/IP. In order to do this, you need a GDB compiled to support the simulation’s target architecture and whichever host you’re running from. The gdb-remote module only supports version 5.0 of GDB, but other versions may work as well. Unfortunately GDB’s remote protocol does not support any version checking, so the behavior is undefined if you use other versions. GDB can be obtained from ftp://ftp.gnu.org. To connect a GDB session to Simics, first start your Simics session and run the gdbremote command, optionally followed by a TCP/IP port number, which defaults to 9123 for historical reasons. This will automatically load the gdb-remote module. When there is a configuration loaded, Simics will listen to incoming TCP/IP connections on the specified port. Run the simulated machine up to a point where you want to run GDB on it. If you want to inspect a user process or dynamically loaded parts of the kernel, this might be easiest to do with magic instructions. For static kernel debugging, a simple breakpoint on a suitable address is easiest. Once Simics is in the desired state, start your GDB session, load any debugging information into it, and then connect it to Simics using the target remote host:port command, where host is the host Simics is running on, and port is the TCP/IP port number as described above. Here is a short sample session: (gdb) set architecture sparc:v9a (gdb) symbol-file vmlinux Reading symbols from vmlinux...done. (gdb) target remote localhost:9123 Remote debugging using localhost:9123 time_init () at /usr/src/linux/include/asm/time.h:52 (gdb) The set architecture command tells GDB to expect instructions from the V9 version of the SPARC architecture. This is not likely to be necessary on other targets. From this point, you can use GDB to control the target machine, using normal GDB commands like continue, step, stepi, info regs, breakpoint, etc. Note that while a remote GDB session is connected to Simics, the Simics prompt behaves a little differently with regards to stopping and resuming the simulation. While the GDB session is at prompt, it is impossible to continue the simulation from within Simics (e.g., by using the continue command). However, once you continue the execution from GDB, you can stop it either from GDB (by pressing control-C), which causes 83

13.2. Using GDB with Simics

the simulation to stop and makes both GDB and Simics return to their prompts. You can also stop the simulation from the Simics prompt (also by pressing control-C). This only makes Simics return to prompt, while GDB will still think the target program is running. In this state, you can continue the simulation from the Simics prompt. You can also force the GDB back to prompt using the gdb0.signal 2 command, which tells the GDB session that the simulated machine got a SIGINT signal. gdb0 here refers to a configuration object created on the fly when a new GDB session connects to Simics. You can connect several GDB sessions to one Simics, and they will all receive one gdbnn object each. Since GDB isn’t the most stable software, especially when using remote debuggging, it unfortunately hangs now and then. To force Simics to disconnect a dead connection, you can use the gdb0.disconnect command. Note that the gdb-remote module does not have any high-level information about the OS being run inside Simics. This means that in order to examine memory or disassemble code, the data or code you want to look at has to be in the active TLB. Note: When using gdb-remote with targets supporting multiple address sizes (such as x86-64 and SPARC), you must have a GDB compiled for the larger address size. For SPARC, run GDB’s configure script with the -target=sparc64-sun-solaris2.8 option.

13.2.1

Remote GDB and Shared Libraries

It takes some work to figure out how to load symbol tables at the correct offsets for relocatable object modules in GDB. This is done automatically for normal (non-remote) targets, but for the remote target, you have to do it yourself. First you need to find the actual address where the shared module is mapped in the current context on the simulated machine, and then calculate the offset to use for GDB’s add-symbol-file command. To find the addresses of the shared libraries mapped into a process’ memory space under Solaris, use the /usr/proc/bin/pmap pid command. The start address of the text segment can be obtained from the Addr field in the .text line of the output from dump -h file. Under Linux, the list of memory mappings can be found in the file /proc/pid/maps (plain text format). The VMA column of the .text line of the output from objdump -h file contains the start address of the text segment. Using these two values, map address and text address, you should use map address + text address as the offset to add-symbol-file (it has to be done this way to compensate for how GDB handles symbol loading). Following is an example from a SPARC running Linux (sim-sh# denotes the shell in the simulated computer): sim-sh# ps PID TTY TIME CMD : 461 ttyS0 00:00:00 bash sim-sh# cat /proc/461/maps 0000000000010000-0000000000060000 r-xp 0000000000000000 08:11 90115

84

/bin/bash

13.3. Symbolic Debugging Using Symtable

000000000006e000-0000000000076000 rwxp : 0000000070040000-0000000070138000 r-xp 0000000070138000-0000000070140000 ---p 0000000070140000-000000007014e000 rwxp : sim-sh# objdump -h /lib/libc-2.1.3.so /lib/libc-2.1.3.so: Sections: Idx Name : 14 .text

000000000004e000 08:11 90115

/bin/bash

0000000000000000 08:11 106505 /lib/libc-2.1.3.so 00000000000f8000 08:11 106505 /lib/libc-2.1.3.so 00000000000f0000 08:11 106505 /lib/libc-2.1.3.so

file format elf32-sparc

Size

VMA

LMA

File off

Algn

000ce338

000000000001e400

000000000001e400

0001e400

2**9

From this we derive that the bash process with pid 461 has /lib/libc-2.1.3.so located at starting address 0x70040000. The .text symbols starts at address 0x1e400, so if we connect GDB to Simics we have to add its symbols with offset 0x70040000 + 0x1e400 = 0x7005e400. Before running the following commands, we stopped Simics using control-C while it was executing code in the bash process: (gdb) dir ˜/glibc-2.1.2/malloc Source directories searched: /home/gustav/glibc-2.1.2/malloc:$cdir:$cwd (gdb) add-symbol-file libc.so.6 0x7005e400 add symbol table from file "libc.so.6" at .text_addr = 0x7005e400 (y or n) y Reading symbols from libc.so.6...done. (gdb) target remote localhost:9123 Remote debugging using localhost:9123 __libc_malloc (bytes=0x14) at malloc.c:2691 2691 if (victim == q) (gdb) next 2693 q = next_bin(q); (gdb)

13.3

Symbolic Debugging Using Symtable

As an alternative to gdb-remote, Simics comes with some symbolic debugging facilities of its own in the symtable module. It is less full-featured than GDB but is easy to use, and it can be scripted in Python.

13.3.1 Symtables and Contexts A symtable object contains the symbolic information for an address space, typically a process or a kernel. The context class provides abstract address spaces. Each processor has a current context, which tells Simics what context object to use for the code it executes at the moment. A context object may have a symtable and virtual-address breakpoints. By default, each processor has the object primary-context as its current context. You may create new 85

13.3. Symbolic Debugging Using Symtable

contexts and switch between them at any time. This allows you to maintain separate debugging symbols and breakpoints for different processes in your target machine.

13.3.2

Sample Session

Here we inspect a running Linux kernel on an UltraSPARC. First, load the module and create an object: simics> load-module symtable Module symtable loaded simics> new-symtable kernel Created symbol table ’kernel’ for context ’primary-context’ simics> kernel.source-path /usr/src>/misc/sources simics> kernel.load-symbols bagle-vmlinux-2.2.14-5.0smp Loading symbols from bagle-vmlinux-2.2.14-5.0smp .[symtable] Symbols loaded at 0x404000 ext2_find_entry (dir=0xfffff80000bbbaf8, name=0xfffff8001e5b4a90 "ptya6", namelen=5, res_dir=0xfffff8001e6f7bb8) at /usr/src/linux-2.2.14/fs/ext2/namei.c:51 51 if (len != de->name_len) So far all good — we have created a new symtable called kernel, and loaded symbols from a kernel binary built with debug info. As you see, Simics responds by telling us what function is executing, and prints out the source line. The source-path step is optional; it merely says that the source file /usr/src/foo/bar can be found at /misc/sources/foo/bar on the simulator host. Now, let’s have a look around and see where we are: simics> stack-trace #0 0x481134 in ext2_find_entry (dir=0xfffff80000bbbaf8, name=0xfffff8001e5b4a90 "ptya6", namelen=5, res_dir=0xfffff8001e6f7bb8) at /usr/src/linux-2.2.14/fs/ext2/namei.c:51 #1 0x481328 in ext2_lookup (dir=0xfffff80000bbbaf8, dentry=0xfffff8001e5b49e0) at /usr/src/linux-2.2.14/fs/ext2/namei.c:178 #2 0x4628a8 in real_lookup (parent=0xfffff8001f764120, name=0xfffff8001e5b49e0, flags=0) at /usr/src/linux-2.2.14/fs/namei.c:254 #3 0x462c78 in lookup_dentry (name=0xfffff8001e5ae00a "", base=0xfffff8001f764120, lookup_flags=0) at /usr/src/linux-2.2.14/fs/namei.c:396 #4 0x462d80 in __namei (pathname=0xfffff8001e5ae000 "/dev/ptya6", lookup_flags=0) at /usr/src/linux-2.2.14/fs/namei.c:465 #5 0x423e70 in sys32_newlstat (filename=0xeffff9c0 (unreadable), 86

13.3. Symbolic Debugging Using Symtable

statbuf=0xeffff918) at /usr/src/linux-2.2.14/arch/sparc64/kernel/sys_sparc32.c:1311 #6 0x40fc94 in linux_sparc_syscall () in bagle-vmlinux-2.2.14-5.0smp Apparently we have caught the kernel in the middle of a file name lookup. We can look at some variables: simics> psym block 6 and go up one step to the calling function, and examine its local variables: simics> up #1 0x481328 in ext2_lookup (dir=0xfffff80000bbbaf8, dentry=0xfffff8001e5b49e0) at /usr/src/linux-2.2.14/fs/ext2/namei.c:178 simics> psym dentry->d_lru {next = (struct list_head *) 0x1e5b4a18, prev = (struct list_head *) 0x1e5b4a18}

13.3.3

Common Commands

As the sample session showed above, the psym command can be used to print a symbolic expression. It may be necessary to quote the argument, so that it does not confuse Simics’ command-line parser: simics> psym "*iptr" 42 The sym command does the same thing, but returns the result to the CLI parser for use as arguments of other commands; simics> x (sym dentry) 10 : 0000 02f5 0000 0000 ffff Note the parentheses needed for grouping. Both psym and sym are evaluated relative the current stack frame. Use up and down to walk up or down the call stack, or frame to jump to a specific stack frame: simics> frame 3 #3 0x51b384 in tty_write (file=0xfffff800001e6940, buf=0x7016c000 (unreadable), count=181, ppos=0xfffff8001f5f4000) 87

13.3. Symbolic Debugging Using Symtable

at /usr/src/linux-2.2.14/drivers/char/tty_io.c:6 It is often useful to find out what code or variables reside at a specific address. Use whereis for this purpose: simics> whereis %i7 in lookup_dentry() at /usr/src/linux-2.2.14/fs/namei.c:405 simics> whereis -d 0x5a6338 jiffies (type long unsigned int) in sched.c The -d flag may be needed to limit the search to data symbols. To do the opposite, find a code address from a file and line number (or just a line number), use pos: simics> pos sys_sparc32.c:1313 4341372

13.3.4

Symbolic Breakpoints

Breakpoints are set using Simics’ break command in conjunction with sym or pos: simics> break (sym tl0_irq11) Breakpoint 1 set on address 0x408960 with access mode ’x’ simics> break (pos sched.c:1531) Breakpoint 2 set on address 0x43b200 with access mode ’x’ It is also possible to set a breakpoint on data (a watchpoint). The following example sets a data breakpoint on the variable “jiffies”, causing the simulation to stop whenever this variable is accessed. The second parameter is the extent of the breakpoint, in bytes. simics> break -r -w (sym "&jiffies") (sym "sizeof jiffies") Breakpoint 3 set on address 0x5a6338, length 8 with access mode ’rw’ See section 13.1 for more information about how to use breakpoints.

13.3.5 Reading Debug Information from Binaries Symbolic information are normally read in using the hsymtablei.load-symbols command as in the example above. Currently only ELF binaries can be used, and the debug info must be in the “stabs” format. Also, the files must be present on the host machine — Simics cannot read directly from the file system of the simulated machine. Here are some things to think about when preparing a binary for debugging: • On some platforms, the GCC compiler does not use the stabs format by default. Use the -gstabs+ option to force stabs (with some GCC extensions) to be used. 88

13.3. Symbolic Debugging Using Symtable • Some versions of the Sun WorkShop (Forte) C compiler do not put the debug information in the final executable, but expect a debugger to read it from the object files directly. This is not supported by Simics, so be sure to use the -xs option when compiling. • If getting sensible stack traces is important, adhere to the target machine’s calling and stack frame conventions. In other words, avoid optimisations such as GCC’s -fomit-frame-pointer. • Currently, only C is supported, not C++. It is possible to debug programs built from a mixture of C and C++ source, but then only symbols from the C part (and those declared extern "C") will be reliably recognised, for name mangling reasons. • It is possible to debug dynamically loaded code by specifying the base address of each module when using load-symbols, but it is easier to just link the code statically when possible. See section 13.2.1 for how to find this address on some systems.

13.3.6

Loading Symbols from Alternate Sources

Sometimes it is desirable to read symbols from a source other than a binary — perhaps all you have is a text file listing the symbols. The hsymtablei.plain-symbols command reads symbols from a file in the output format of the BSD nm command. Example: 000000000046b7e0 T iunique 000000000062ba40 B ivector_table 00000000005a6338 D jiffies The hexadecimal number is the symbol value, usually the address. The letter is a type code; for this purpose, D, B, and R are treated as data and anything else as code. The symbols do not have any C type or line number information associated with them, but you will at least be able to do stack traces and find the location of statically allocated variables.

13.3.7

Multiple Debugging Contexts

It can occasionally be useful to debug programs running in different address spaces. Since Simics only simulates the hardware, it does not keep track of such operating system concepts such as processes, so it has to be told what context is active by the user. As an example, here we study a Linux system running the user-space process apache. Assume the kernel symbols were loaded into a symtable in the primary-context as in the sample session above. First we create a context and symtable for the apache process: simics> cpu0.set-context apache-ctx simics> new-symtable apache-syms 89

13.3. Symbolic Debugging Using Symtable

Created symbol table ’apache-syms’ for context ’apache-ctx’ simics> apache-syms.load-symbols apache-debug-binary Loading symbols: apache-debug-binary [symtable] Symbols loaded at 0x110c8 To decide which context to use, we can look at the %pstate register (this being a SPARC), and use the set-context command manually. This can also be automated, using the following Python snippet: def set_my_context(dummy): cpu = conf.cpu0 reg = SIM_get_control_register_number("pstate") pstate = SIM_read_control_register(cpu, reg) if pstate & 4: cpu.current_context = conf.primary_context else: cpu.current_context = conf.apache_ctx SIM_hap_register_callback("Core_Back_To_Front", set_my_context, 0) By hooking the function onto the Core_Back_To_Front hap, the right context is automatically set for interactive debugging. Note that this simple example does not distinguish between different user-mode processes. Alternatively your context tracker could be run whenever the CPU mode changes, by using the Core_Mode_Change hap: def set_my_context(dummy, cpu, old_mode, new_mode): if new_mode == Sim_CPU_Mode_Supervisor: cpu.current_context = conf.primary_context else: cpu.current_context = conf.apache_ctx SIM_hap_register_callback("Core_Mode_Change", set_my_context, 0) This is accurate but somewhat slower, since it may be run very frequently. It is possible to write more sophisticated context trackers, trapping all relevant CPU and MMU state changes and change context accordingly. This may be necessary if you use virtual-address breakpoints in multiple contexts.

13.3.8

Scripted Debugging

It is frequently useful to access data symbolically from Python scripts. Scripts access the debugging facilities using the symtable interface and attributes of the symtable class. These are documented in the Simics Reference Manual. For instance, here is a short script to print out the names of mapped files of the currently executing task in Linux. It uses the eval_sym function, which takes a C expression and returns a (type, value) pair. 90

13.3. Symbolic Debugging Using Symtable

eval_sym = SIM_get_class_interface("symtable", "symtable").eval_sym def eval_expr(cpu, expr): return eval_sym(cpu, expr, [], ’v’) def ptr_str(typed_val): (type, val) = typed_val return "((%s)0x%x)" % (type, val) def walkmap(task): cpu = current_processor() task = eval_expr(cpu, "current") mmap = eval_expr(cpu, ptr_str(task) + "->mm->mmap") while mmap[1]: file = eval_expr(cpu, ptr_str(mmap) + "->vm_file") if file[1]: name = eval_expr(cpu, ptr_str(file) + "->f_dentry->d_name->name") print name[1] mmap = eval_expr(cpu, ptr_str(mmap) + "->vm_next") In this example, current is a register variable which (in kernel mode) holds a pointer to the currently active task. (This is not true for Linux on x86 hardware.) The expression parsed by eval_sym may contain casts, struct member selection and indexing.

91

13.3. Symbolic Debugging Using Symtable

92

Chapter 14

Network Simulation The ethernet-central module for Simics Central provides a functional simulation of ethernet networks. Multiple networks can be simulated, and the ethernet-central module can function as router between them, including one or more real networks if available to the host. Congestion on the network is not modeled, and packets are always delivered with the (per interface) minimum latency. Note: For all examples that are given in this chapter, simulated machines are assigned IP addresses in the range of 10.10.0.1 to 10.10.255.254. It is possible to use any valid IP address, but it simplifies the configuration of a real network connection to have all simulated interfaces allocated in a single, private address range. Address allocation for private networks is described in RFC 1597 of the IETF (http:// www.ietf.org/rfc/rfc1597.txt?number=1597).

Note: Running multiple instances of Simics Central on the same host should be avoided, as TCP/IP port number and/or local file socket name will collide. It is however possible to avoid this if the -port and -file command line options to Simics Central are used.

14.1

Setting up a Simulated Network

A basic Simics Central configuration will include one ethernet-central object and one ethernet-network object. The ethernet-network instance represents a simulated network, and simulated ethernet devices are connected to this object. The network object will handle the basic mapping of IP to ethernet (MAC) addresses, including the ARP and RAPR functionality. With that said, a minimal configuration would look like this: OBJECT ether0 TYPE ethernet-central { networks: ("net0")

93

14.2. Connecting to a Simulated Network

} OBJECT net0 TYPE ethernet-network { ethernet-central: "ether0" netip: "10.10.0.0" netmask: "255.255.255.0" }

This will create a single simulated network called net0 with IP addresses in the range of 10.10.0.1 to 10.10.0.255. The ethernet-central object will connect itself to this network, using first address available on the network (in this case 10.10.0.1). The address 10.10.0.255 is reserved for IP broadcasts, thus addresses in the range of 10. 10.0.2 to 10.10.0.254 are available for simulated devices on the network. From the Simics Central command line, network objects can be listed using the network command: simics> network Ethernet Central (ether0) networks: Name Address Mask net0 10.10.0.0 255.255.255.0 simics>

A new network can be added with the network-add command: simics> ether0.network-add "net1" "10.10.1.0" "255.255.255.0" ... simics> network Ethernet Central (ether0) networks: Name Address Mask net0 10.10.0.0 255.255.255.0 net1 10.10.1.0 255.255.255.0 simics>

The network-add command will automatically add a route for the newly created network in the internal routing table of ethernet-central. Refer to section 14.4 for more information about the routing table.

14.2

Connecting to a Simulated Network

For now we assume that we have Simics Central up and running with the ethernetcentral module loaded, and at least one instance of ethernet-central and ethernet-network each. Note: It is important that Simics Central is started first, before all Simics clients. If Simics Central was started with the [simics]/home/central/central.simics script, the setup should look something like this (the last run command is necessary to start the simulation in Simics Central): 94

14.3. Connecting to a Real Network

simics> network Ethernet Central (ether0) networks: Name Address Mask net0 10.10.0.0 255.255.255.0 simics> route Ethernet Central (ether0) IP routing table: Destination Gateway Netmask 10.10.0.0 * 255.255.255.0 simics> run

Network net0

Status enabled

In this example we will use a target machine model called enterprise. The Simics instance is started with the -central option, which means that Simics will connect to a Simics Central running on the specified host: # ./simics -x enterprise-1p.simics -central localhost Simics startup wrapper. Copyright (c) 2000-2002 Virtutech AB.

On hosts that support file sockets (i.e., sockets opened with the AF_UNIX address family), Simics will use a local file socket for communicating with Simics Central (if running on the same host). If Simics and Simics Central is running on different hosts or if AF_UNIX type sockets are unsupported, a regular TCP/IP socket will be used. This can also be controlled to some extent by command-line parameters to Simics Central. From the Simics command line, we can connect the simulated network adapter to a network object in Simics Central. In the enterprise model, this network adapter is called lance0: simics> lance0.connect net0 simics>

This will be confirmed in the Simics Central console with the following output: [ether0] Device registering with Ethernet Central: [ether0] simics: simics at localhost [ether0] device: lance0 [ether0] network: net0 [ether0] requested addr: 10:10:10:10:10:30 [ether0] assigned addr: 10:10:10:10:10:30

14.3

Connecting to a Real Network

The ethernet-central module allows connection to a real LAN. Similar to routing packets between simulated networks, the Simics Central will route packets to and from the real network. For this to work, the simulated clients must be configured with Simics Central as the gateway. Machines on the real network must also be configured to use Simics Central as a router to the simulated networks. 95

14.3. Connecting to a Real Network

Note: Connecting the simulated network to the real network requires some knowledge of network administration issues. Before proceeding, there are some important issues to be aware of: • Simics Central will not route packets to and from the host that it is running on. This means that the machine Simics Central is running on will not be able to communicate with the simulated network. • To enable connection to a real LAN, Simics Central needs to read from and write to the raw network device. This normally requires root privileges. Machines which need to communicate with the simulated network(s) must have a route to Simics Central. How this is done depends on the host OS. In the following examples, host is the host on which Simics Central is running. Linux: /sbin/route add -net 10.10.0.0 netmask 255.255.0.0 gw host Solaris: /sbin/route add -net 10.10 host Windows: route add 10.10.0.0 mask 255.255.0.0 host These commands will cause all packets to IP-addresses beginning with 10.10 to be routed to Simics Central on host host. The command connect-real-network connects Simics Central to the network. Once connected and Simics Central is running (use the continue command) the Unix commands ping and traceroute (or tracert on Windows) can be used to check the connection between Simics Central and the real network. Try ping 10.10.0.1 for example (from a real machine; no simulated machine is necessary since Simics Central has its own IP-number). The following is a example of how to run traceroute from a real machine to Simics Central. Simics Central is running on a host called matrix, and traceroute is run on a host called leeloo. am@leeloo: traceroute 10.10.0.1 traceroute to 10.10.0.1 (10.10.0.1), 30 hops max, 38 byte packets 1 central (10.10.0.1) 1.948 ms 0.404 ms 0.372 ms am@leeloo: Note that Simics Central must be running, or it will not answer any requests. To check that a DNS entry is ok, use the command nslookup from a real host: nslookup 10.10.0.5 10.10.0.1

96

14.4. Manipulating the IP Routing Table

14.4

Manipulating the IP Routing Table

The ethernet-central module contains an internal IP routing table that is used for packet routing between simulated as well as real networks. In most applications there is no need to manipulate this table manually, as entries are added automatically (e.g., when running the central.simics initialization script). However, for some special applications (e.g., connecting the ethernet-central module to several real networks), this table must be modified. The routing table is stored in the ethernet-central module as an attribute called routing-table. The preferable way to view this table is to use the route command: simics> route Ethernet Central (ether0) IP routing table: Destination Gateway Netmask 10.10.0.0 * 255.255.255.0 10.0.0.0 * 255.255.255.0 default * 0.0.0.0 simics>

Network net0 real-net real-net

Status enabled enabled enabled

The output is quite similar to route command available on many systems. The destination and netmask fields specify a target that can be either a network (i.e., a range of addresses) or a single host (with netmask 255.255.255.255). For packets with this target as their destination, the network field specifies the network object that should be used. Only routing table entries that are enabled will be regarded. New entries can be added to the routing table with the route-add command, and existing entries can be removed from the table using the route-del command: simics> ether0.route-del "default" "0.0.0.0" real-net "*" simics> ether0.route-add "192.168.0.0" "255.255.0.0" real-net simics> route Ethernet Central (ether0) IP routing table: Destination Gateway Netmask Network Status 10.10.0.0 * 255.255.255.0 net0 enabled 10.0.0.0 * 255.255.255.0 real-net enabled 192.168.0.0 * 255.255.0.0 real-net enabled simics>

The destination address and the netmask identify the target, and should be given as strings in dotted decimal form. If the target is a single host, the netmask should be given as "255.255.255.255". If the destination address or the netmask that are given to the route-add command is specified as "*", the actual value is taken from the network object. This assumes that the network object has been correctly initialized.

14.5 Services in ethernet-central The ethernet-central module offers some standard network services. By using them, the need of a server on the simulated network, or a real network connection, can be avoided. 97

14.6. Booting with DHCP

The services are RARP, DNS, BOOTP, DHCP, (a very simple) Bootparam/whoami RPC, and (simplified) TFTP.

14.6

Booting with DHCP

By using DHCP, several simulated clients can boot from identical disk images without the need of configuring each one independently. Every client will get its network settings from the DHCP server. First the client must be configured to boot using DHCP. The procedure for this is OS dependent, and not described here. Then the Simics Central must be setup with enough information for the booting clients. Example of attributes to add: OBJECT ether0 TYPE ethernet-central { dns: (("10.10.0.1", "central", "network.sim"), ("10.10.0.5", "donut", "network.sim"), ("10.10.0.6", "bagle", "network.sim")) networks: ("net0") } OBJECT net0 TYPE ethernet-network { ethernet-central: "ether0" arp: (("10.10.0.1", "10:10:10:10:10:10"), ("10.10.0.5", "10:10:10:10:10:12"), ("10.10.0.6", "10:10:10:10:10:14")) netip: "10.10.0.0" netmask: "255.255.255.0" ownip: "10.10.0.1" } This tells Simics Central about the IP to ethernet address mapping, and also the IP to name (and domain name) mapping.

14.7

Booting with BOOTP

The Simics Central can reply to BOOTP requests, redirecting the booting client to a TFTP server. simics> ether0.bootp-server

98

14.8. Transferring Files with TFTP

14.8

Transferring Files with TFTP

Simics Central’s ethernet-central module supports the Trivial File Transfer Protocol (TFTP, RFC 1350) which allows you to transfer files between the simulated target system and the host system without needing to use the real network interface (since this also requires you to set up a route and be root on the machine). Files that should be transferred from the host system to the simulated client should be located in the same directory as where Simics Central is executed. Files transferred from the simulated client to the host, will also end up in the directory from where Simics Central is started (typically [simics]/home/central). TFTP can be used to transfer the OS kernel by the boot PROM, or interactively like FTP, using the tftp command found on Unix systems. TFTP is based on UDP and each package is acknowledged before the transfer is allowed to continue. Due to this, transferring large files between a Simics and Simics Central can be slow. Simics only fetches packages on regular basis controlled by the min-latency attribute of the simulated network card. Therefore, reducing the min-latency attribute in the network card will increase transfer performance. Currently, the TFTP support in the ethernet-central module does not support concurrent sessions. That is, several files can not be transferred at the same time.

14.9 Troubleshooting Real Network Configuration Problems There are several common pitfalls one might encounter when trying to connect a simulated network with a real one. A network monitoring tool such as tcpdump is invaluable when debugging problems with the real-network support in Simics Central. The following tcpdump invocation will print all ICMP-packets sent on the network: root# tcpdump -v -x icmp Another useful tool is Ethereal, which is a graphical packet analyzer that can disect several kinds of protocols and can keep track of TCP-connections and many other things. Ethereal is available from http://www.ethereal.com. Below is a list of problems commonly encountered when setting up the real-network support. The term “real host” refers to a physical machine which is trying to communicate with a simulated machine on the simulated network, or with Simics Central itself. Real host has no route If trying to communicate with the simulated network from a machine which does not have a route to the simulated network, the packets will never be seen by Simics Central. tcpdump will show where the packets are sent. If there is no route to Simics Central, the packets will be sent to the default gateway, which will probably ignore them. 99

14.9. Troubleshooting Real Network Configuration Problems

Simulated OS has no route If the real host has a route to Simics Central, but the simulated OS does not have a route to Simics Central, ping-packets from the real host will be passed into the simulated network, received by the simulated OS, but the simulated OS will not know what to do with them, since it does not have a route to Simics Central. To figure out if this is the case, use the command netstat -r under Linux and Solaris. Under Windows, just type route print at the command prompt. Note that these commands should be executed in the simulated machines. The simulated OS should have a default route to 10.10.0.1. Real host and Simics Central on the same host As noted earlier, Simics Central does not route packets to and from the host it is running on. More specifically, when receiving packets from the real network, it discards any packets which has the same source or destination IP-number as the Simics Central host. In other words, Simics Central ignores packets sent to or from the host it is running on. The reason for this is partly because not all operating systems allow sniffing packets to/from the current host and partly because that if we accepted packets to and from the current host, Simics Central would get much more traffic since all outgoing packets from Simics Central would get sniffed back in. Real host and Simics Central not on the same net Simics Central can not communicate with hosts on a different local net than the host it is running on. So, make sure all machines which should be able to communicate with Simics Central are located on the same physical network. An example which will not work is to attempt to run ftp ftp.download.com in a simulated machine in order to download some program into the simulated machine. In order to do that, you need an FTP-server connected to your local net.

100

Chapter 15

Cache Simulation 15.1

Simulating a Simple Cache

Simics comes with a generic-cache module that can be used to simulate common cache hierarchies. To add a simple L1 data cache to your system, you only need to include one object description in your .conf file: OBJECT gc0 TYPE generic-cache { lines: 128 lsize: 32 assoc: 2 enabled: 1 cpu: cpu0 queue: cpu0 read_hit_penalty: 1 read_miss_penalty: 8 write_hit_penalty: 2 write_miss_penalty: 10 } In a Simics configuration script, you would do (using Python): @SIM_new_object("generic-cache", "gc0") @conf.gc0.lines = 128 @conf.gc0.lsize = 32 @conf.gc0.assoc = 2 @conf.gc0.cpu = conf.cpu0 @conf.gc0.queue = conf.cpu0 @conf.gc0.read_hit_penalty = 1 @conf.gc0.read_miss_penalty = 8 @conf.gc0.write_hit_penalty = 2 101

15.2. Multiple Level Caches

@conf.gc0.write_miss_penalty = 10 @conf.gc0.enabled = 1 You can consult the Target Guide corresponding to your configuration to get more details about adding a new object. As can be seen above, the generic cache allows you to specify parameters like number of cache lines, line size and associativity. Whether to use write back or write through, and write allocate policy can also be specified. The replacement policy is random. Full documentation on the generic cache attributes can be found in the Simics Reference Manual. The next thing you need to do is to connect the cache to the memory hierarchy. This is done by setting the timing-model attribute in the memory space of the CPU you want to connect the cache to. For example, if the CPU is attached to a memory space called phys_mem0, you would need to add something like: OBJECT phys_mem0 TYPE memory-space { timing_model: gc0 map: ((0x00000000, memory0, 0, 0, 0x60000000)) } or in a script: @conf.phys_mem0.timing_model = conf.gc0

Note: If you are using a version of Simics that supports multiple outstanding transactions, you should place the cache after the consistency controller instead of connecting directly it to the memory space. After having executed some code in Simics, you should be able to look at cache status and cache statistics using gc0.print-status and gc0.statistics respectively. Note: For performance reasons, instruction fetches are not sent to the caches by default. Read the section 15.4 to learn how to send instruction fetches to the cache depending on the performance and the statistics you want to gather.

15.2 Multiple Level Caches Suppose that we want to simulate the cache system illustrated in figure 15.1, a dual CPU system with separate instruction and data L1 caches and a unified L2 cache connected to each CPU. First of all we need a way of separating data and instruction transactions. This can be done by configuring the cpu0 instruction and data caches as: 102

15.2. Multiple Level Caches

CPU0

I

CPU1

D

I

L2

D

L2

RAM

Figure 15.1: A typical cache system

OBJECT icache0 TYPE generic-cache { lines: 512 lsize: 32 assoc: 4 enabled: 1 cpu: cpu0 queue: cpu0 read_miss_penalty: 8 write_miss_penalty: 10 write_through: 1 write_allocate: 0 next_cache: l2_cache0 } OBJECT dcache0 TYPE generic-cache { lines: 1024 lsize: 32 assoc: 4 enabled: 1 cpu: cpu0 queue: cpu0 103

15.2. Multiple Level Caches

read_miss_penalty: 8 write_miss_penalty: 10 write_through: 1 write_alloc: 0 next_cache: l2_cache0 } Note that we cannot set the timing_model attribute in phys_mem0 to both icache0 and dcache0. The solution is to use the id-splitter module included with Simics. Its purpose is to split instruction and data accesses and forward them to two different objects. To connect our cache system to the memory hierarchy, we have to add the following to the .conf file: OBJECT splitter0 TYPE id-splitter { ibranch: icache0 dbranch: dcache0 } and set the timing_model attribute of phys_mem0 to splitter0. The generic-cache module defaults to be a write allocating, write back cache, but we want our L1 caches to be write through and non-write allocating, so we change this using the write_through and write_alloc attributes. The next_cache attribute is used to connect our L1 caches to a lower (i.e., further away from the CPU) level cache. Now, our I and D caches are set up, and we create an L2 cache: OBJECT l2_cache0 TYPE generic-cache { queue: cpu0 lines: 2048 lsize: 64 assoc: 1 enabled: 1 cpu: cpu0 read_miss_penalty: 100 write_miss_penalty: 100 previous_caches: (icache0, dcache0) next_snoop: l2_cache1 } This will setup a 128 kB direct mapped cache with 64 byte lines. The previous_caches attribute in l2_cache0 is used to let the L2 cache know which caches are connected to it from above (i.e., closer to the CPU) and need to be flushed when an L2 line is invalidated. Since we want to simulate a dual CPU system the procedure above needs to be repeated to add a cache hierarchy to cpu1; i.e., we need to add splitter1, icache1, dcache1, and l2_cache1 objects and connect them to the memory space of cpu1. When simulating multi-processor cache hierarhies, a separate memory space for each processor needs to 104

15.2. Multiple Level Caches

cpu0

cpu1

phys_mem0

phys_mem1

timing_model

map

map

splitter0 ibranch

splitter1 dbranch

icache0 next_cache

dcache0

icache1

dcache1

next_cache l2_cache0

next_snoop

l2_cache1

prev_caches

prev_caches phys_mem_common

Figure 15.2: Objects and attributes used to configure a typical cache hierarchy using Simics

be used in order to connect a different timing model to each CPU. The different memory spaces can then be made to point to a common memory-space object in order to make the RAM shared between the processors. In our .conf file we might do like this: OBJECT phys_mem0 TYPE memory-space { timing_model: splitter0 map: ((0x00000000, phys_mem_common, 0, 0, 0xFFFFFFFFFFFFFFFF)) } OBJECT phys_mem1 TYPE memory-space { timing_model: splitter1 map: ((0x00000000, phys_mem_common, 0, 0, 0xFFFFFFFFFFFFFFFF)) } OBJECT phys_mem_common TYPE memory-space { map: ((0x00000000, memory, 0, 0, 0x60000000)) } OBJECT memory TYPE ram { image: memory_image } The next_snoop attribute specified in the L2 caches is used to let each cache communicate with the other caches in the system in order to maintain cache coherency. The 105

15.3. Generic-Cache Features and Limitations

coherency protocol used is a simple MESI variant. Figure 15.2 above shows the objects in our example cache hierarchy together with the attributes that connects them. If you are simulating machines with more than two processors you will probably want to use Python scripts to set up caches and memory spaces automatically instead of specifying them one by one in your configuration files.

15.3 Generic-Cache Features and Limitations Generic-cache is not a perfect cache simulation and it does not support all the features you may need in simulating real systems caches. Generic-cache uses a flat hierarchy model system, that is a total stalling time is computed as soon as a memory transaction is sent to the first level cache, by propagating eventual miss transactions to the lower levels. When the transaction has stalled, the caches are updated by letting the caches lines modified by the transaction be used by other transaction as hit or to be replaced. When write-back is enabled, generic-cache issues a copy-back operation everytime a dirty line is replaced. Generic-cache tries to work around some limitations in some of Simics’ targets that cannot stall some usual memory operations (e.g., instruction fetches on x86). It will try to cache them but this may lead to strange situation where transactions need to be skipped because they can not wait on a cache line despite they would need to. The statistics provided by generic-cache contain the different cases encountered. Generic-cache uses as much as possible the internal simulator caches to avoid slowing down the simulation. This means that it won’t see all the hit transactions and thus may only compute an approximative miss ratio (the total number of miss transactions is exact however). You can however disable this optimization by setting the attribute exact_stats to 1. The cache will then see all the transactions and compute the miss ratios on this basis. Generic-cache can only be attached to one CPU. Attaching it to several CPUs at the same time will create conflicts and sometimes prevent the simulation from running. If you plug other memory hierarchies behind a generic-cache, take care that setting the cache in write-back mode may force it to generate multiple outstanding transactions (with the copy-back operations).

15.4 Observing Instruction Fetches To increase Simics performance, instruction fetches are not sent to the cache by default. The command instruction-profile-mode allows you to decide how instruction fetches will be handled. This command is dependent on the architecture of the target machine, and its behaviour may differ between, for example, SPARC and x86. • If you do not wish to observe instructions fetches (default setting), you can set the instruction profile mode to no-instruction-profile • If you wish to generate memory traffic through the caches, but you do not care about having correct hit ratios, you can use the instruction-cache-access-trace mode. 106

15.5. Understanding Generic-Cache Statistics

Simics will avoid sending instruction fetches that are on the same cache line. Note that this mode does not work for the x86 architecture, where you should always use the full instruction set mode. • If you wish the caches to see all the instruction fetches (if you enable exact_stats in generic-cache for example), you should choose the mode instruction-fetch-trace. Note that on the SPARC architecture, you should issue the command before loading a configuration, because it uses the instruction-profile-line-size attribute in the sim object, and this value is fixed when a configuration has been loaded.

15.5

Understanding Generic-Cache Statistics

The hgeneric-cachei.statistics command will print out all the statistics describing the behavior of the cache: Statistics of cache: generic-cache calls to the cache transactions non-cacheable non-stallable blocked blocked and skipped sent to next level

174844135 173339474 302466 2021008 226 99 4677950

Transactions seen by the cache: data read 109415698 data write 63621310 instr. fetches 0 Transactions seen by the cpu while the cache was enabled: read 109684006 write 63621309 instr. fetches 555854799 data read misses 992695 (0.91%) data write misses 533278 (0.84%) instr. fetch misses 0 replacements copy back inhibits invalidates

1485830 345299 302565 0

For a cache simulation, the following statistics are the most important: 107

15.5. Understanding Generic-Cache Statistics

transactions The number of transactions that were cached. non-cacheable Transactions skipped because they were non-cacheable. blocked Transactions that were blocked waiting for a cache-line to be empty. They were executed later on so they just stalled a bit longer than they would normally have. It doesn’t include the blocked and skipped transactions (see below) blocked and skipped Transactions that couldn’t be cached properly because they couldn’t stall (see limitations above). data read, data write, instr. fetches The total number of cached transactions of a specific type. read, write, instr. fetches The total number of transactions that the CPU is reporting when the cache was enabled. It includes non-cacheable transactions and other transactions that eventually never reached the cache (e.g., ROM access). data read misses, data write misses, instr. fetch misses The total number of misses of a specific type. The ratio is computed as follow: if exact_stats is enabled, the ratios is the total miss divided by the total of transactions seen by the cache (of the given type). If exact_stats is 0, the ratios are computed using the values reported by the cpu. replacements Thenumber of lines replaced. copy back The number of copy-back operations when emptying a cache-line. invalidates The number of transactions that could not be cached. It should be the sum of the non-cacheable transactions and the blocked but skipped transactions.

108

Chapter 16

Understanding Simics Timing By default, Simics has a simple model of how long time it takes to execute an instruction and in what order instructions from multiple processors are simulated. This model can be extended with progressively more accurate and detailed views of time.

16.1

Simulation Mechanism

The concept of time in Simics is different from in a real machine and the accuracy may vary depending on how Simics is configured. Fundamentally Simics is an event driven simulator, with a maximum time resolution of a clock cycle. The length of a clock cycle is user defined, and in multiprocessor systems may differ between processors. Examples of events are device reply interrupts, time interrupts, and instruction execution. When multiple events are scheduled to occur at the same cycle, the following order applies: first, any events scheduled for the cycle other than instruction execution; next, any events scheduled to occur at the instruction; finally, the instruction execution event is executed. If multiple events are scheduled for either the cycle or the instruction, they occur in the order they were posted. Events can also be scheduled to occur after a specific number of steps have executed. A step is either an instruction that completes, an instruction that generates an exception, or an external interrupt. This is typically used to support debugging breakpoints (e.g., stop simulation after 1000 instructions). For Simics to have some way of determining the execution time for a given program, there has to be some definition of how long instructions take to execute. When a single processor machine is simulated, this is quite simple; there will be exactly one notion of time with an execution mode defining instruction execution and timing interfaces controlling the latency of execution. When multiprocessors are simulated this become somewhat more complex as each processor could potentially have its own notion of time. Ideally all processors could run in parallel with perfect synchronization. However, perfect synchronization is exceedingly slow, so Simics serializes execution when simulating multiprocessors to improve performance. Simics does this by dividing time into segments and serializing the exe109

16.2. Execution modes

cution of separate processors within a segment. The length of the segment is referred to as the quantum and is specified in cycles. As in the single processor case, instruction execution and latency are defined with execution modes and timing interfaces. Simics does not define the order in which the processors are serialized, which means that if causality is to be preserved, processor-to-processor communications must have a minimum latency of one quantum. Another consequence of serializing the execution is that Simics will maintain strict sequential consistency. However, through careful use of the memory hierarchy interface, the user can choose to simulate other consistency models. The number of cycles in a quantum can be set by changing the attribute cpu_switch_ time in the global sim object. Thus, if the switch is set to 10 and the first processor runs at 4 MHz, the quantum is 2.5 microseconds. A second processor running at 1 MHz will run 2 or 3 cycles every other quantum. Breakpoints do not affect this schedule so that interaction remains non-intrusive. Note that if you are single-stepping (stepinstruction) on cpu0 have executed the last cycles of a quantum, the next single step will cause all other processors to advance a quantum and then cpu0 will stop after an instruction. For the multi-processor simulation to run efficiently the switch should not be set too low, as a cpu switch causes simulator overhead. It should not be set below 10, and should preferably be set to 50 or higher. Note that all of the above remains essentially the same when running a distributed simulation using Simics Central. As part of simulating the entire system Simics also models the parts of the system outside of the processor. By default, Simics models most devices with fairly simple algorithms that perform the basic execution of the device with a simple timing model. Although the source code to all of the devices has not been released, the interfaces are public, allowing the user to replace any supplied device model with a more detailed implementation.

16.2

Execution modes

Execution modes define what sort of events will occur and what ordering requirements those events must follow. The definitions of what events are used to model an instruction are a natural consequence of describing the way in which internal operations of a CPU are modeled. Simics provides two basic executions modes: an in-order execution mode (available for all processor models) and an out-of-order execution mode (introduced in Simics 1.4 for SPARC processors). As always there is a tradeoff between performance and complexity. In this case the complexity of the timing model, though both modes execute programs with equal execution accuracy. The choice of mode is per processor and can be changed dynamically.

16.2.1

In-Order Execution

The default in-order execution mode is quite simple. In this mode each instruction becomes a single event. Instructions are scheduled sequentially in program order. This means that other instructions cannot occur until a previous instruction has completed, even if it takes many simulated cycles to execute. For example, a memory operation that misses in a cache stalls the issuing CPU. This assumes that the user has written a 110

16.2. Execution modes

memory timing model using the memory hierarchy interface. Thus this mode not only preserves the basic instruction set abstraction that instructions execute discretely and sequentially, it implements it. By simulating the minimum detail necessary for accurate execution this mode achieves quite high performance. In a multiprocessor context it can become clear that instruction execution is not actually atomic. If an instruction is stalled such that execution extends across a quantum boundary it is possible for another processor to observe and manipulate the partially executed instruction. The separate phases of instruction execution that can be stalled are instruction fetch memory access and data memory access. If any of these accesses are stalled later accesses are not issued until the stall has completed. As instructions are strictly in order stalling any phase of an instruction stalls the entire CPU. Note: This mode is the default mode for all processors models. However, all processors do not allow stalling memory accesses. The following restrictions apply: • SPARC processors can stall all memory accesses • x86 processors can stall data memory accesses if you run a special “stall” binary (for performance reasons). • Other processors do not allow you to stall memory operations, although you can still observe them.

16.2.2 Out-Of-Order Execution The out-of-order execution mode trades performance for the ability to capture the essential features of a modern pipelined out-of-order processor. In particular the out-of-order execution mode can produce multiple outstanding memory requests that do not necessarily occur in program order. The Simics out-of-order mode breaks instructions into several phases that can be scheduled independently. Scheduling of instruction phases must not violate any dependencies but is otherwise unconstrained. The phases fall into three categories: the begin event, the end event, and all other phases of execution. The begin event takes a program counter value and fetches the corresponding instruction. The end event occurs when all previous instructions have ended and the instruction execution is complete. It writes all machine visible state and deallocates the internal data structures. This removes the possibility of rollback and resembles the commit stage of a modern pipeline. Other events, such as ALU operations, are not visible to the user and will occur as soon as their input dependencies have been resolved. To simplify understanding, the out-of-order execution mode can be thought of as a dataflow machine with unconstrained resources. Thus, unlike the in-order model, multiple instructions can be in flight, and if one phase of an instruction stalls only those instructions with true (register write-read) dependencies will be affected. Memory dependencies are not observed by the out-of-order mode, but are handled by a consistency controller. As the consistency controller is intimately tied to timing it is discussed in the 111

16.3. Modeling Time

timing section. The default controller enforces a set of rules that implement a conservative consistency model.

Note: This mode is only implemented by the SPARC processors models. You must run a special binary to activate the out-of-order mode.

16.3

Modeling Time

As stated above the Simics execution modes define what sorts of computation are scheduled as events. However they do not define how the latencies of these events are determined. Simics provides a framework for calculating these latencies with timing interfaces. The user can choose to either use the default timing models provided or write their own timing models by using the interfaces described below. The user may choose to build timing models using any combination of timing interfaces, though some of the interfaces require particular execution modes.

16.3.1

Default Timing Models

The timing models provided with Simics do not model any particular processor. Rather, Simics presents two generic abstractions that both relate simulated time to the number of instructions executed. When using the in-order execution mode the default is that each instruction takes exactly one clock cycle. In the multi-processor case this means that at any point in simulated time all processors will have executed the same number of instructions (ignoring startup conditions). However in real time some of the processors will have finished a given quantum before others have started meaning that processors do not actually advance in lock step. When running the out-of-order mode the default timing model is more complex as multiple instructions can occur simultaneously. As mentioned above the out-of-order mode can be thought of as an idealized dataflow machine. Each phase of instruction operation is infinitely fast but the transfer of data from a producer to a consumer takes one cycle. Thus while an instruction could complete all phases of simulated operation in a single simulated cycle, the number of data dependences on the critical path bounds program execution time. Additionally, the default model does not include a branch predictor potentially limiting program parallelism. Thus Simics observes control and data dependences to have a latency of one cycle. One consequence of this is that when operating with the out-of-order mode there is no predefined correspondence between number of instructions that have executed and the current time. As stated above a consistency controller is used to observe memory dependences. The default controller does not add any explicit latencies, but has a conservative consistency model that can impose delays to achieve correctness. 112

16.3. Modeling Time

16.3.2

Memory Hierarchy Interface

The memory hierarchy interface gives the user access to Simics memory transactions. There are two memory interfaces per memory space, a timing-model and a snoopdevice. The timing model gives access to memory transactions before Simics accesses the memory space and allows the user to stall the transactions. The snoop device gives access after Simics does the memory access, this allows the user to observe the values loaded or stored but does not allow stalling. Other than this, the two interfaces are identical. The interfaces have four modes of operation which control the references passed to the interface. In all modes all data references that access the memory space will be visible. The difference in the modes is in the visibility of instruction references. The modes are: • Every instruction fetch is visible. • The first instruction fetch from a cache line. • Each instruction fetch following a branch execution. • No instruction fetches. The choice of mode should be governed by interest and desired simulation performance. Timing Model Interface The timing-model memory system interface allows the user to model the performance of a memory hierarchy. When this interface is active each memory request generated by the execution model calls a user-defined memory-system timing model. This call includes all relevant information about the memory access, physical address, virtual address, size, and so forth. The call is expected to return the number of cycles to stall the instruction causing the access. If the call returned a nonzero stall time, Simics will stall the instruction for the returned number of cycles and then reissue the call to the timingmodel. This will continue until the user module returns a stall time of zero cycles. The interface is designed to be simple and generic with the intention of allowing the user to build a multi-level cache hierarchy by connecting multiple instances of a cache model in series. When running in the in-order execution mode, the user module has access to a set of internal Simics structures (STCs) that filter accesses to the memory system. Only memory access to addresses not cached in an STC will call the user module. If the user wishes to observe every memory access, the STCs can be disabled entirely, though this is detrimental to performance. The intent is to allow the user to filter out any request that require no action by the memory hierarchy. By default no memory system timing models are installed and memory accesses are stalled for zero cycles. When running in the out-of-order execution mode a consistency controller is required and the STCs are disabled. This means that memory transactions are not filtered before reaching the memory system module. As in the in-order execution mode there 113

16.3. Modeling Time

is no default memory system timing model and memory accesses are stalled for zero cycles. The Snoop Device Interface The snoop device interface allows the user to create a trace of memory transactions. The callback to the user module from Simics is identical to the one used by the timing model with three exceptions. First, the snoop callback is issued after the transaction completes allowing the user to inspect the value loaded or stored. Second, the value loaded can be changed. Third, an error will occur if a stall time other than 0 is returned. If the user chooses to implement a memory system model that connects to both the timing-model and snoop device interfaces the user can both stall accesses and change the return values of memory reads. This allows the user to implement a consistency model more relaxed than sequential consistency, though this places the burden of correctness on the user.

16.3.3

The Consistency Controller

Note: This is only used by the out-of-order execution mode The consistency controller uses the memory system interface but is actually part of implementing a correct ordering of memory requests and is thus by definition part of the functional model. The purpose of the consistency controller is to implement the processor’s consistency model using a structure that is superficially similar to a store buffer. When using the in-order execution mode Simics presents memory references inorder making the task of the consistency controller trivial to the point that it is omitted from the system. When using the out-of-order execution mode Simics will present memory references as soon as the instruction is dataflow ready without regard for potential address dependencies. This request stream is therefore much more aggressive than any currently published consistency system and it is the job of the consistency controller to place memory transactions into an order that correctly implements the desired consistency model. Simics provides a default consistency controller that enforces a model at least as conservative as Sun’s Total Store Ordering (TSO1). The consistency controller connected in series between the timing-model interface and any user defined timing-model modules. The user is free to replace the controller, though in this case it is the user’s responsibility to maintain correctness. It is expected that a user designed consistency controller would also implement the bypassing features commonly found in store buffers.

16.3.4

Micro-Architectural Interface

Note: This is only used by the out-of-order execution mode

114

16.4. Event Handling

The micro-architectural interface allows the user to model the performance and detailed micro-architecture of a processor core. The micro-architectural interface requires the out-of-order execution mode described above. The user creates a resource model of the processor being simulated, leaving the functional execution to Simics. The interface allows many levels of modeling, from a simple bandwidth model to a detailed resource usage model. The intent of this timing interface is to allow the user to write a resource model, not a processor simulator. This may come as quite a paradigm shift to those used to writing detailed timing simulators. Using the Simics interface execution is explicitly split from the modeling of performance. Simics will simulate execution while the user is expected to model time by keeping track of the resources in use. This framework allows users to concentrate their efforts on performance rather than operation. For example a user need only develop a scheme to allow renaming of condition codes without having to debug the details of ensuring that the correct branch reads the correct condition codes. To get more information, refer to the Simics Out-Of-Order Guide.

16.4

Event Handling

Simics supports a general event handling mechanism. Each processor object has two event queues: a step queue and a time queue. The resolution in the time queue is a processor cycle as defined for that processor in the configuration. For each processor cycle all events scheduled for that cycle are performed. Time can either be specified as a number of processor cycles or a floating point number specifying a number of seconds, but this will be rounded down to a processor cycle, except between zero (inclusive) and one which will be rounded up to one. In the step queue, events will appear after a number of program counter steps. The step count is the sum of successfully completed instructions, issued instructions that caused exceptions, and system level handled interrupts. For example, when doing a memory access, the memory system may return a number of cycles the processor should stall before continuing execution. This will delay the event posted in the step queue versus an event posted in the time queue. The step queue is typically used for programming and debugging related events (e.g., stop after 100 instructions) and some pipelined effects (e.g., interrupts are disabled during the next instruction). Multiple events may be posted in the same cycle/step - if scheduled to occur in the same cycle/step they will be handled in FIFO order, i.e., first posted is first handled. Events may be posted with zero step delay, assuring that they get handled prior to any new instructions on that processor. An exception to this this is if the instruction has started to execute, in which case the event must be posted with minimum delay of 1 step. 115

16.5. The Simulator Translation Cache (STC)

16.5

The Simulator Translation Cache (STC)

A key to the design of the memory simulation in Simics is the Simulator Translation Cache (STC). It works like a filter within the interpreter engine. A detailed simulation of memory can be implemented by a combination of a variety of modules, including an MMU (TLB), data/instruction cache module, and any other devices that might be involved, depending on the target architecture. Since it would be very expensive to involve all relevant modules upon every memory operation, the STC is designed to cache the most pertinent information, and to be able to serve most memory operations directly. In particular, the STC filter is intended to contain the following information: • The current logical-to-physical translation for the address • A count of number of accesses to the address The general idea is thus that the STC will contain information about “harmless” memory addresses, i.e., an access would not cause any device state change or side-effect. A particular memory address is mapped by the STC only if: • The given logical-to-physical mapping is valid. • An access would not affect the cache state (even when considering replacement policy). • An access would not affect the MMU (TLB) state. • There are no breakpoints, callbacks, etc associated with the address. There are several STC tables, in fact there are (at least) six of them per simulated processor. They cover the combinations of (read, write, execute) and (supervisor, user), thus treating separately various types of access types.

116

Part III

Extending Simics

117

Chapter 17

Creating a Simics Module The functionality of Simics can be extended by user written modules. There are two kinds of modules in Simics; devices that model the functional behavior of real devices, and extensions that extend Simics in other ways. There is no hard distinction between devices and extensions; it is possible to create modules that both model devices and extend Simics in other ways. It is also possible to model several devices in the same module by implementing several classes in it. Actually, a Simics module can do just about anything. Modules are usually written in C/C++, but Python can also be used for most things. The following section is mostly oriented towards module development in C/C++. For an example of what the source code of a device may look, refer to the sampledevice module. This module defines a dummy device with a few simple commands, showing how to register a configuration class with attributes and interfaces, and how to add commands to the Simics frontend (CLI).

17.1

Setting up a Build Environment

Before any modules can be built, it is necessary to run the configure script. The configure script determines information specific to the current host, needed by make (such as compiler features and the location of various libraries). Note: The Simics makefiles require GNU make (a.k.a. gmake), version 3.77 or later, which is available from ftp://ftp.gnu.org/gnu/make. In the following text, when you’re asked to run gmake, this refers to running the GNU make binary, which may or may not be called gmake, depending on your installation. The configure script should be run in the host directory: cd simics/host ../configure -q

119

17.1. Setting up a Build Environment

If you want to see what configure actually does, skip the -q option. Running configure may take a minute or two, depending on how fast the machine is. It sometimes happens that configure gets the wrong value to certain configuration variables. For example, if your PATH environment variable is set so that the wrong compiler is found, you will need to tell configure explicitly which C-compiler to use. The preferred way of tell configure which C-compiler to use is to pass it as an option to configure: ../configure CC=/usr/bin/gcc If you need to rerun configure with the same parameters (for example, after installing another compiler), do ./config.status --recheck && ./config.status

Note: Most options to configure are ignored when building user extensions. The most useful ones are -q (do not print checking for ... messages), and -C (cache results). Sometimes it is desirable to make more persistent changes in how configure works. This is done by creating and editing the following files, replacing user with your user name: $HOME/simics-host-defaults.user This is a shell script which is “sourced” by configure. Normal Bourne shell script syntax applies. This file control things like the location of libraries. See config/ host-defaults.host in the Simics distribution for a sample (it contains the default settings for host). $HOME/simics-host-flags.user This file is included by gmake. Normal gmake syntax applies. NOTE: In Simics 1.6.0 and later, it is no longer possible to set the value of CC and CXX in a hostflags.∗ file. CC and CXX should be set either on the command line to configure, be set in the environment, or found in the PATH environment variable. If you want to change the value of CFLAGS, don’t do that manually (configure will warn you if you do). Chances are that you will break something. If you want to add a compiler flag, set the variable CFLAGS_USER (or CXXFLAGS_USER if you want to set it only for the C++ compiler). For example: gmake my-module CFLAGS_USER=-DUSE_EXTRA_DEBUG_STUFF If you want to compile for debugging, set the variable CFLAGS_MODE as: gmake my-module CFLAGS_MODE=’$(DEBUG_CFLAGS)’

120

17.2. Compiling Modules

DEBUG_CFLAGS is a late bound variable, so it needs to be properly quoted to prevent premature evaluation. There is also a variable DEBUG_CXXFLAGS if you want to pass debug-flags only to the C++ compiler. If you want to change the debug flags, you may set DEBUG_CFLAGS explicitly. There are variables WARN_CFLAGS, OPT_CFLAGS (the default), and PROF_CFLAGS. For example, if you want to tweak optimization in your module, do: gmake my-module OPT_CFLAGS=’-O6’ Turning off warnings: gmake my-module WARN_CFLAGS=” The Simics makefiles are quite terse. If you want to see exactly what commands gmake runs, set the variable VERBOSE to yes. gmake my-module VERBOSE=yes By default, the Simics makefiles will colorize its output. If you do not want this, or if your terminal does not approve of ANSI color codes, run: gmake my-module COLORIZED_MAKE=no

17.2

Compiling Modules

The source code for Simics modules are located in simics/src/devices and simics/ src/extensions, where each module has its own subdirectory. Modules are not compiled in their source directories, but in a separate build directory simics/host/lib/. The name of the host directory depends on the host platform used, e.g., x86-linux, v9-sol8-32, or v9-sol8-64. To compile and link a module, run: cd simics/host/lib gmake module_name The makefile in the lib directory will try to find a module with the specified name, and compile it. It is also possible to specify the name of a group instead of the module name, in which case all modules belonging to that group will be compiled. Examples of groups are x86, sunfire, and alpha. Run gmake with no arguments to get a list of groups and other build targets. The makefile will then ask for the number of the target to build. # gmake Available targets: 121

17.3. Module Makefiles

’all’ ’headers’ - one of:x86 sunfire alpha central x86_64 ’list’ - lists all individual modules ’clean’ ’clobber’ Options: TGT= execute sub-target in target Makefile FLG= flags to gmake for the target Please enter make target: 1) all 4) sunfire 2) headers 5) alpha 3) x86 target ?

17.3

6) central 7) x86_64

8) clean 9) clobber

Module Makefiles

In order to make the build environment in Simics recognize a module as a build target, there must be a makefile called Makefile in its source directory. A module makefile must set up a number of make variables and then call the generic makefile for Simics modules. The following is an example of a module’s Makefile: MODULE_DIR=NCR53C90 MODULE_NAME=FAS366U MODULE_CFLAGS=-DFAS MODULE_CLASSES=FAS366U SRC_FILES=esp.c include $(SIMICS_BASE)/src/devices/common/device-makefile

• MODULE_DIR is the name of the module source directory; this may be different from the module name. • MODULE_NAME is the name of the module in Simics, i.e., the name that loadmodule will use. • MODULE_CFLAGS (optional) are module specific flags for the compiler. • MODULE_LDFLAGS (optional) are module specific flags for the linker. 122

17.4. Adding Modules to the Build List • MODULE_CLASSES (optional) is a space separated list of configuration classes that this module registers. This information is used by SIM_get_class() to determine that this module should be automatically loaded when one of the listed classes is requested. • SRC_FILES is a list of all source files for the module. You should only list C or C++ files here. Note that C source files must have a .c suffix, and that C++ source files must have a .cc suffix. • EXTRA_VPATH (optional) can be set to instruct the generic module makefile to look for source files in more directories that in MODULE_DIR. • EXTRA_OBJ_FILES (optional) may contain names of object files already compiled, that should be linked into the final module. The user can also add new rules to the makefile, either before or after the inclusion of the generic device-makefile. This is usually not needed.

17.4

Adding Modules to the Build List

The file simics/config/modules.list.dist contains a list of all modules that can be built in the current enviroment. It is not recommended to modify this file. New user-defined modules should instead be added to the modules.list-local file in the same directory. At the beginning of modules.list, a number of groups are defined corresponding more or less to the different architecture Simics simulates (e.g, alpha, arm,...). Here is an example: sunfire

| v9

| v9 | -DTARGET_VA_BITS=64 -DTARGET_PA_BITS=64 [...]

The first line is a definition of the sunfire group, as indicated by the first field in that line. The second field in this line defines the cpu architecture the group belongs to. The third field is a list of other groups that depends on sunfire. Last on the line is a list of CFLAGS defines (i.e., flags passed to the C compiler). The rest of the file consists in a list of all modules that are available, specifying among other things for which groups they should be compiled. If we take the trace module as an example: trace

| ARCH | alpha

ia64

v9 x86 x86_64 |

The trace module will be compiled for the groups alpha, ia64, v9, x86 and x86_64. The ARCH set at the beginning indicates how the module will be specialized. The possible values are: ONE One generic module will be compiled. This is the case when the module doesn’t depend on anything specific regarding the simulated architecture. 123

17.5. Standard Module Target Defines

BIT One module will be compiled for each type of memory address (32 bits and 64 bits). This is needed if your module is manipulating physical or virtual addresses whose size changes depending on the simulated architecture. If you are using the TARGET_VA_BITS and TARGET_PA_BITS defines in your code, you should at least choose to compile your module as BIT ARCH One module will be compiled for each simulated architecture. This is needed when the module is using specific features of a simulated architecture. If you are using defines like TARGET_SPARCV9, or if you plan to use memory_transaction_t (which is specific to each architecture), then you should compile your module as ARCH. Depending on this setting different defines are added to the CFLAGS at compile time. The defines that are set are documented in the section Standard Module Target Defines below. They are also listed in the group definition. The resulting filenames will be libmodule-group.so: ONE BIT ARCH

libhost-cdrom-common.so libide-32.so libgeneric-cache-v9.so

Note: To use the new Simics 2.0 API then ARCH2, BIT2 and ONE2 should be used instead. This is recommended for new modules, and to prepare for migration to Simics 2.0.

17.5

Standard Module Target Defines

The include files for Simics will export different types and slightly different struct layouts depending of the target chosen. The following defines should not be set in the module’s Makefile, instead they are set depending on the entry in the file modules. list.dist, or in modules.list-local. Examples of target defines are: TARGET_VA_ BITS, TARGET_PA_BITS, TARGET_SPARCV9, TARGET_ULTRA, TARGET_X86. Depending on which TARGET_architecture has been defined, one of TARGET_LITTLE_ ENDIAN and TARGET_BIG_ENDIAN will be defined. For modules with the variant type set to BIT, only the TARGET_VA_BITS and TARGET_ PA_BITS defines are set, each to either 32 or 64, defining the size of virtual and physical address words.

17.6

Standard Module Host Defines

There are a number of defines that are set depending on the host that the module is being compiled on. They are usually not needed, but useful in some special cases. Ex124

17.7. User Defined Module Version Numbers

amples: HOST_64_BIT, HOST_32_BIT, HOST_BIG_ENDIAN, HOST_LITTLE_ENDIAN and CROSS_ENDIAN. There are also defines specifying the host architecture and host operating system. All these defines are set in the Simics include file global.h.

17.7

User Defined Module Version Numbers

It is possible to set a user defined version number (or string) in loadable modules. This is done by setting the USER_VERSION define in MODULE_CFLAGS in the module’s Makefile. The version number will be printed by the list-modules and list-failedmodules commands.

17.8

Module Loading Support

When Simics starts, it will check all modules for their supported architecture and word size. Only modules that match the running Simics binary will be available for loading into Simics. While scanning the modules, Simics will also check what classes the module will register when it is loaded. This way modules can be loaded automatically when classes they define are used in a configuration. If a module does not match the current Simics, it will be added to the list of failed modules. This list can be displayed with list-failed-modules, that takes an optional parameter -v for more verbose output. simics> list-failed-modules MODULE ARCH DUP WORDSIZE VERSION LINK ----------------------------------------------------------8042 X X image X Z8530 X hostfs X libMK48T08_64.so X sample-memhier X libsymtable-v9.so X libspitfire-mmu.so X libsun4u-ac.so X The columns after the module name (or file name in the case of a link error) indicate different kinds of errors. There is an X in each matching column. ARCH means that this module could not be loaded because it was compiled for a different target architecture version of Simics. DUP flags that this module has the same name as another module found in the Simics module search path, and that this one was overridden. WORDSIZE means that this module was compiled for a different target architecture word size. VERSION means that the module was created for another, non-compatible, version of Simics. LINK means that this module cannot be loaded into Simics because 125

17.9. The Object Directories

of unresolved symbols. Use list-failed-modules -v to see the actual error message from the run-time module loader.

17.9

The Object Directories

As described earlier, the source file directories are separate from the directory where you run gmake when compiling modules (which is the same directory where the target module file is created). However, the working directory of the make process can be found in [simics]/host/obj/modules/module, where module is the name of the module with a suffix that can be either a bitness (-32 or -64), an architecture (like -x86 or -v9), or -common for modules that can be loaded into all Simics versions. This working directory will contain any intermediate compilation files, like object (.o) files.

126

Chapter 18

Inside a Simics Module 18.1

Module Loading and Unloading

There are only two functions that a module must contain. They are the init_local() and fini_local() functions, that are called when the module is loaded and unloaded, respectively. They are defined as: DLL_EXPORT void init_local(void) { } DLL_EXPORT void fini_local(void) { } These functions allow the module to do whatever it needs to do when it is loaded and unloaded, for example registering classes it implements or registering hap callbacks for haps it is interested in. Note that Simics does not support unloading of modules yet, so fini_local() is usually empty. A module may depend on a configuration to already be loaded when it is initialized, for example it may need to interact with a cpu object. If the module is loaded before Simics has read a configuration it can register a hap callback that is called once a configuration has been loaded. This can be done by writing the init_local() function like this: DLL_EXPORT void init_local(void) { if (SIM_initial_configuration_ok()) { my_initial_config(NULL);

127

18.2. Implementing Module Functionality

} else if (SIM_hap_register_callback("Core_Initial_Configuration", my_initial_config, NULL) < 0) { pr("[my_module] Failed installing hap handler\n"); return; } }

This will call the function my_initial_config() immediately if a configuration has already been loaded, otherwise it will register my_initial_config() as a callback to the Core_Initial_Configuration hap. my_initial_config() will then be called with the second parameter to SIM_hap_register_callback() as parameter once a configuration has been successfully loaded. my_initial_config() should be declared like this: void my_initial_config(void* param) { // Initialization code here... }

18.2

Implementing Module Functionality

A Simics module can do virtually anything, a module could even start a new thread that executes a completely different program within Simics. To be of any practical use, however, a module usually has to interact with either Simics, other modules, or the user in some way. The Simics API provides a number of mechanisms that can be used for this. The most important of these are classes and objects, interfaces, haps and events. The Simics API consists of a large number of functions, and a complete listing can be found in the Reference Manual.

18.2.1

Classes and Objects

Chapter 9 explains how a Simics configuration is described in terms of objects and attributes. Each device is represented by an object whose attributes correspond to the state of the device. As a matter of fact, most Simics modules work the same way; they create objects that provide new functionality through their attributes and commands. Simics objects are instantiated from classes. A class describes an object type and its attributes. Simics handles the attributes automatically so that Simics objects seem like normal objects in Python (with attributes being data members). In C you can use the functions SIM_get_ attribute() and SIM_set_attribute() to manipulate the attributes of objects. 128

18.2. Implementing Module Functionality

18.2.2

Interfaces

When more complex interaction between objects (than what is possible through attributes) is needed, Simics can use interfaces. An interface specifies a number of functions that must be provided by any class that implements this interface. A class can both implement interfaces to make itself accessible to other classes and access other classes through interfaces they implement. One of the most important interfaces for a device class is probably the io-memory interface. Implementing the io-memory interface enables a class to be mapped into a memory space and be accessed by the simulated machine. Another important interface is the event-poster interface, which should be implemented by all classes that post events. Other interfaces can be used for things like raising processor interrupts or implementing PCI device functionality. A complete list of all interfaces and functions for handling interfaces can be found in the Reference Manual.

18.2.3

Events

Sometimes a module needs to execute some code a fixed amount of simulated time into the future. This can be achieved by posting an event, which will cause a callback function to be called when a specified amount of time has passed. There are two event queues in Simics, the time queue which measures simulated time, and the step queue that measures simulated steps. Devices should generally use the time queue, unless they are interested in the exact number of cpu steps. A device that wants to raise a timer interupt every 10 ms is an example of a module that should use the time queue. A profiling module that wants to sample the program counter every tenth step should on the other hand use the step queue. The chapter 16 describes events in more detail. All functions used to work with events can be found in the Reference Manual.

18.2.4

Haps

A module may also want to react to certain Simics events. This may both be events related to the simulated machine, like processor exceptions or control register writes, and other kinds of events, like Simics stopping the simulation and returning to the command line. In Simics such events are refered to as haps. To react to a hap a module can register a callback function to the hap. This callback function will then be called every time the hap occurs. Again, a complete list of all haps, descriptions of what parameters the callback functions should take and all functions used to register callbacks and manipulate haps can be found in the Reference Manual.

18.2.5

Commands

A module that interacts with the user usually creates a number of commands, which can be invoked by the user from the command line. Commands can either be bound to a class or to the global namespace. Commands bound to classes are used to manipulate individual instances of that class, for example, most devices have a status command 129

18.3. Implementing Classes and Objects

that prints the state of the device. Global commands can be used for things that don’t pertain to a specific object. Commands are defined in a separate Python file in the module’s directory, named commands.py. Chapter 19 describes how to add new commands in detail.

18.3

Implementing Classes and Objects

Most Simics modules implement classes and create objects of these classes. This section describes how to create classes, add attributes to the classes, register interfaces to the classes and create objects.

18.3.1

Classes

A module that implements a Simics class must register the class with Simics. This is done by filling in class_data_t structure with information about the class and then calling the SIM_register_class() function with the name of the class and the class_ data_t structure. The class_data_t structure and the SIM_register_class() function look like this: typedef struct class_data { new_instance_t new_instance; delete_instance_t delete_instance; default_get_attr_t default_get_attr; default_set_attr_t default_set_attr; const char *description; class_kind_t kind; } class_data_t; conf_class_t * SIM_register_class(const char *name, class_data_t *class_data); The class_data parameter should be initialized as follow: • new_instance – This is a function responsible for creating new objects of this class. Its role is described in the next section. • delete_instance – This is a function responsible for destroying objects. It can be set to NULL, since Simics doesn’t support destruction of objects yet. • kind – The class kind tells Simics whether objects of this class should be saved when a checkpoint is created: – Sim_Class_Kind_Vanilla class instances will be saved as part of checkpoints (devices are usually declared this way). – Sim_Class_Kind_Pseudo class instances will never be saved. 130

18.3. Implementing Classes and Objects

– Sim_Class_Kind_Session is not used for the time being and thus has the same meaning as Sim_Class_Kind_Pseudo • description – This field should contain a description of the class. The default_get_attr and default_set_attr fields should be set to NULL. SIM_register_class() returns a pointer to a conf_class_t structure which is used internally by Simics to keep track of the class information. This pointer can be used when refering to the class in calls to other functions. When a module is loaded in Simics, the function init_local() is called. It is usually in this function that classes are registered. A simple initialization function could look like this: DLL_EXPORT void init_local(void) { class_data_t cdata; conf_class_t *my_class; memset(&cdata, 0, sizeof(cdata)); cdata.new_instance = my_new_instance; cdata.description = "This is my class"; cdata.kind = Sim_Class_Kind_Session; my_class = SIM_register_class("my-class", &cdata); // Other initializations... }

Note: Classes and modules are completly separate entities, thus it is possible for a module to declare several classes or none at all. Remember that classes registered in a module should be listed in the MODULES_CLASSES variable in the module’s Makefile. This allows Simics to automatically load the required modules when reading a configuration file.

18.3.2 Objects Each Simics class must have a corresponding object structure that is used to hold data about individual objects. Simics’ class system supports a very limited form of inheritance, where all classes must inherit the class conf_object_t, the basic configuration object class, either directly or indirectly. When declaring an object structure the first element must be the object structure of the class it inherits. An object structure for a class that directly inherits conf_object_t is declared as: 131

18.3. Implementing Classes and Objects

typedef struct my_object { conf_object_t obj; // Other variables... } my_object_t; A Simics object contains (in the conf_object_t field) all the information related to its class and its attributes. When an object is created, the new_instance() function declared in the class definition is called. The new_instance() function is responsible for allocating an object structure for the new object and initializing the all fields except the conf_object_t part. A typical function would look like this: static conf_object_t * my_new_instance(parse_object_t *parse_obj) { my_object_t *mo = MM_ZALLOC(1, my_object_t); // Initializations... return (conf_object_t *) mo; } When inheriting some other class the object structure should instead include the object structure of that class as its first field. The new_instance() function should also call some function that initializes the object structure of the inherited class. A very common class to inherit is log_object_t, which automatically provides log facilities to the inheriting classes. The log_object_t part of the object structure can be initialized by calling the SIM_log_constructor() function. The object structure and new_instance() function would then look like this: typedef struct my_object { log_object_t log; // Other variables... } my_object_t; static conf_object_t * my_new_instance(parse_object_t *parse_obj) { my_object_t *mo = MM_ZALLOC(1, my_object_t); SIM_log_constructor(&mo->log, parse_obj); // Initializations... return (conf_object_t *) mo; }

132

18.3. Implementing Classes and Objects

18.3.3

Attributes

A Simics class can register attributes that will act as data members for all objects instantiated from this class. In Python, attributes are undistinguishable from usual object data members, but for Simics, they are only an abstraction: an attribute is defined by its type and a pair of get/set functions. When an attribute is read (i.e., when the SIM_ get_attribute function is used on the object), the corresponding get function is called. Likewise, when an attribute is written to, the set function is executed. These functions can perform any kind of operation provided they return a value (for get) and accept a value to be written (for set). Attribute values are defined with the structure attr_value_t defined as follow: typedef enum { Sim_Val_Invalid Sim_Val_String Sim_Val_Integer Sim_Val_Floating Sim_Val_List Sim_Val_Data Sim_Val_Nil Sim_Val_Object } attr_kind_t;

= = = = = = = =

0, 1, 2, 3, 4, 5, 6, 7

struct attr_list { integer_t struct attr_value };

size; *vector;

struct attr_data { integer_t uint8 };

size; *data;

struct attr_value { attr_kind_t kind; union { const char *string; integer_t integer; double floating; attr_list_t list; attr_data_t data; conf_object_t *object; } u; }; According to kind, the right union member should be used to get the value of an 133

18.3. Implementing Classes and Objects attribute. The get function returns always an attr_value_t and the set function always accept an attr_value_t as parameter. Many other Simics functions return an attribute value using this structure as well. A Simple Attribute Let us consider a simple example, where my_object_t is defined as: typedef struct my_object { conf_object_t obj; int foo; } my_object_t; We want to implement an attribute called counter, thus we need a pair of set/get functions. counter will internally use foo to keep its value. The pair of get/set functions could be defined as: static attr_value_t get_counter(void *dont_care, conf_object_t *obj, attr_value_t *idx) { my_object_t *mo = (my_object_t *) obj; attr_value_t ret; ret.kind = Sim_Val_Integer; ret.u.integer = mo->foo; return ret; } static set_error_t set_counter(void *dont_care, conf_object_t *obj, attr_value_t *val, attr_value_t *idx) { my_object_t *mo = (my_object_t *)obj; if (val->kind != Sim_Val_Integer) return Sim_Set_Need_Integer; mo->foo = val->u.integer; return Sim_Set_Ok; } In the get_counter() function, obj is the object that owns the attribute and dont_care will be described in the next section. Note that obj can be safely cast to my_object_t (conf_object_t is used as a “base type” here). The function creates an attr_value_t variable that will be of type Sim_Val_Integer and contain the value foo. It then returns this attribute value. 134

18.3. Implementing Classes and Objects The set_counter() function on the other hand takes a val argument which contains the value to be written. After verifying the type of the value, it extracts it from the attr_ value_t structure and sets foo. The return value is of type set_error_t, which is defined as follow: typedef enum { Sim_Set_Ok, Sim_Set_Error_Str, Sim_Set_Need_Integer, Sim_Set_Need_Floating, Sim_Set_Need_String, Sim_Set_Need_List, Sim_Set_Need_Data, Sim_Set_Need_Object, Sim_Set_Object_Not_Found, Sim_Set_Interface_Not_Found, Sim_Set_Illegal_Value, Sim_Set_Attribute_Not_Found, } set_error_t;

A Pseudo Attribute In the previous example, the attribute counter is a direct representation of the value foo inside the object. Now let us add an attribute called add_counter that will increase foo by a given value when the attribute is set, and do nothing when the attribute is read. This would give us the following code: static attr_value_t get_add_counter(void *dont_care, conf_object_t *obj, attr_value_t *idx) { attr_value_t ret; ret.kind = Sim_Val_Invalid; return ret; } static set_error_t set_add_counter(void *dont_care, conf_object_t *obj, attr_value_t *val, attr_value_t *idx) { my_object_t *mo = (my_object_t *)obj; if (val->kind != Sim_Val_Integer) return Sim_Set_Need_Integer; mo->foo = mo->foo + val->u.integer; 135

18.3. Implementing Classes and Objects

return Sim_Set_Ok; } The function get_add_counter() always returns an invalid attribute, which is a way to tell the caller that the operation get can not be performed on this attribute. Since this function is used for almost all pseudo attributes, it is often known and implemented as get_write_only(). The semantics of set_add_counter() are also slightly different, since the function actually adds a value to foo. It is thus possible to create real attributes whose value corresponds to a real variable in an object, and pseudo attributes which are only used as object “methods”. An Indexed Attribute The idx parameter is provided if the attribute can be indexed. The index value is then given as an attr_value_t. In Python, this would correspond to the following code: object.attr[i] = a b = object.attr[’a string’] c = object.attr[i:j] The index value would take the values a, ’a string’, and i:j when the corresponding get/set functions are called. Let us add an array of counters to our previous example: typedef struct my_object { conf_object_t obj; int foo[10]; } my_object_t; If we declare the counter attribute to be integer indexed, the get/set functions could look like this: static attr_value_t get_counter_array(void *dont_care, conf_object_t *obj, attr_value_t *idx) { my_object_t *mo = (my_object_t *) obj; attr_value_t ret; ret.kind = Sim_Val_Invalid; if (idx->kind != Sim_Val_Integer) return ret; if (idx->u.integer < 0 || idx->u.integer >= 10) return ret;

136

18.3. Implementing Classes and Objects

ret.kind = Sim_Val_Integer; ret.u.integer = mo->foo[idx->u.integer]; return ret; } static set_error_t set_counter_array(void *dont_care, conf_object_t *obj, attr_value_t *val, attr_value_t *idx) { my_object_t *mo = (my_object_t *)obj; if (idx->kind != Sim_Val_Integer) return Sim_Set_Illegal_Value; if (idx->u.integer < 0 || idx->u.integer >= 10) return Sim_Set_Illegal_Value; if (val->kind != Sim_Val_Integer) return Sim_Set_Need_Integer; mo->foo[idx->u.integer] = val->u.integer; return Sim_Set_Ok; } As shown above, it is also possible to use strings and Python slices as index. An index corresponding to a slice is provided as a list of two elements, the first and the last element that should be included. Note that this is a slightly different syntax from Python where the second value is the first non-included element. This means that: object. attr[i:j] will be translated into a Sim_Val_List containing two elements, i and j − 1.

18.3.4

Registering Attributes

Once a class is registered, the function SIM_register_attribute() can be called to add a new attribute definition: int SIM_register_attribute(conf_class_t *class_struct, const char *attr_name, get_attr_t get_attr, lang_void *get_attr_data, set_attr_t set_attr, lang_void *set_attr_data, attr_attr_t attr, const char *doc); The parameters of SIM_register_attribute() are the following: 137

18.3. Implementing Classes and Objects • class_struct – This is the class structure returned by SIM_register_class(). The new definition will be added to this class structure. • attr_name – The name of the attribute. • get_attr, set_attr – The get and set function for the attribute. • get_attr_data, set_attr_data – These parameters are user-defined. They are passed to the get/set functions as the dont_care parameters introduced before. This allows passing one extra argument. • attr – This is the type of the attribute. It tells Simics how the attribute should be saved and addressed. It is defined (in a simplified form) as: typedef enum { Sim_Attr_Required, Sim_Attr_Optional, Sim_Attr_Session, Sim_Attr_Pseudo, Sim_Init_Phase_0, Sim_Init_Phase_1, Sim_Attr_Integer_Indexed, Sim_Attr_String_Indexed, Sim_Attr_List_Indexed, } attr_attr_t; The basic type of an attribute is the following: – Sim_Attr_Required – The attribute has to be declared with a value when an object is created in a configuration file. It will also be saved during checkpointing. – Sim_Attr_Optional – The attribute is not mandatory when loading a configuration file. It will be saved during checkpointing. – Sim_Attr_Session – The attribute is only used in the current run and won’t be saved during checkpointing. – Sim_Attr_Pseudo – The attribute is not actually a real attribute but a command in disguise. It does not represent any meaningful value and won’t be saved during checkpointing. Other values can be added (using a bitwise or operation) to the basic type of the attribute: 138

18.3. Implementing Classes and Objects

– Sim_Init_Phase_0, Sim_Init_Phase_1 allow a simple form of priority: attributes declared with the Sim_Init_Phase_1 type will always be initialized after all the others when a configuration is read. Sim_Init_ Phase_0 is the default value. – Sim_Attr_Integer/String/List_Indexed specify if an attribute can be indexed and which index types are valid. If we use the examples above, the attributes counter, add_counter and counter_array would have the following definition: SIM_register_attribute(my_class, "counter", get_counter, 0, set_counter, 0, Sim_Attr_Required, "A counter"); SIM_register_attribute(my_class, "add_counter", get_add_counter, 0, set_add_counter, 0, Sim_Attr_Pseudo, "Command to add a value to the counter"); SIM_register_attribute(my_class, "counter_array", get_counter_array, 0, set_counter_array, 0, Sim_Attr_Optional | Sim_Attr_Integer_Indexed, "Array of counters");

18.3.5

Registering Interfaces

Interfaces allow more complex interaction between a module and Simics (or between modules) then attributes do. Interfaces also allow a level of abstraction, so that the implementation of an interface becomes independent of the interface itself. This is useful when several devices provide the same kind of functionality, for example, the iomemory interface is implemented by all devices that can be mapped in a memory space. As all these devices implement the same interface the memory space can treat them the same way. An interface is basically implemented as a structure of function pointers. Each class that implements an interface provides its own set of the functions required by the interface, and then registers this interface with Simics using the SIM_register_interface() function. A class that wants to interact with another class through an interface uses the SIM_ get_interface() to retrieve the interface structure of function pointers. It can then call the other object using the functions in the structure. The functions SIM_register_interface() and SIM_get_interface() are declared as: 139

18.4. Posting Events

int SIM_register_interface(conf_class_t *class_struct, const char *interface_name, interface_t *interface_ptr); void * SIM_get_interface(const conf_object_t *object, const char *interface_name);

18.3.6

Creating Objects

Objects are created automatically by Simics if they are present in a configuration file. Objects can also be created by calling the SIM_new_object() function: conf_object_t * SIM_new_object(conf_class_t *conf_class, const char *instance_name); In Python, the first argument can actually be a string that will be converted to the corresponding class definition. Using SIM_new_object() directly should be a rare event since objects are usually created automatically from the configuration or created in the init_local() function by a module (like trace-module) when it doesn’t make sense to have several objects of the same type. Other modules usually provide cli commands that create objects internally (using this function).

18.3.7

Examples

Several modules are provided in source code as examples to illustrate Simics’ possibilities. Among them, sample-device and sample-memhier are two relatively simple examples of Simics object system.

18.4

Posting Events

When a module wants to execute some code an amount of simulated time into the future it can post an event to the time queue using the SIM_time_post() function. This will cause a specified callback function to be called with a specified argument, when the specified amount of time has passed. The SIM_time_post() function takes five arguments specifying the object whose time queue should be used, the amount of time until the event occurs, whether just the processor whose queue is used or the whole machine should be synchronized when the event occurs, the callback function that should be called and the parameter for the callback function. 140

18.5. Simics Header Files

If the module for some reason changes its mind and wants to remove an event it has posted earlier, it can use the SIM_time_clean() function, specifying the object, callback function and parameter. A module may also check how long time is left until an event occurs using SIM_ time_next_occurence(), again specifying the object, callback function and parameter. The time left to the event is returned in cycles. If a module wants to post an event a number of simulated steps into the future it should instead post its events to the step queue. Posting to the step queue is very similar to posting to the time queue, but the functions SIM_step_post(), SIM_step_clean() and SIM_step_next_occurence() should be used instead. A more detailed discussion on the time and step queues can be found in chapter 16. Documentation of all the functions used for manipulating events can be found in the Reference Manual.

18.5

Simics Header Files

Modules for Simics should include the following files: #include #include #include #include

"global.h" "simics_api.h" "simmalloc.h" "c-utils.h"

The file global.h will set the host defines, and it should be includes as early as possible. However, it is not necessary to include it explicitly, since it is included in simics_api.h. The file simics_api.h defines the interface to Simics, i.e., the Simics API. simmalloc.h contains Simics own malloc handling, VTMEM. This file can be omitted, but is very useful when debugging the module. The last file, c-utils.h, defines various macros, datatypes and functions that are not part of the Simics API, but still useful when writing in C/C++.

18.6

System Calls and Signals

This section gives a brief overview of how signals are handled in Simics. This only applies to Simics versions running on host operating systems that implement POSIX style signals (e.g., Linux and Solaris). Simics always has the real-time interval timer running (cf. the setitimer(2) man page about ITIMER_REAL), with a timeout of a couple of seconds. This serves two purposes: it asserts that system calls will be interrupted after a while and it makes it easier to find erroneous code that fails to check if a system call was interrupted. If the host operating system allows it, Simics will register its built-in signal handlers to make system calls restartable after the signal has been handled (cf. the SA_RESTART flag in the sigaction(2) man page). 141

18.7. Text Output

However, only some system calls are restartable, so when writing modules for Simics, you have to make sure that you restart the other system calls yourself: do { res = accept(sock, &saddr, &slen); } while (res == -1 && errno == EINTR);

18.7 Text Output Since Simics has its own handling of text output, which allows users to redirect output to several recipients, the standard C library output routines should not be used from within a Simics module. However, by including the simics_api.h header file, some C library function names are redefined as preprocessor macros, which call the Simics versions of these functions instead. E.g., vprintf is redefined as: #undef vprintf #define vprintf(str, ap) SIM_printf_vararg(str, ap) This should work just fine for most applications, but if you, for some reason, need to call the actual C library functions, you can either #undef the replacement definition of that function, or insert #define SIM_BC_NO_STDOUT_REDEFINE before including simics_api.h. See the section about SIM_BC_NO_STDOUT_REDEFINE in the Simics Reference Manual for details about these macro definitions. Whenever Simics is requested to write output using the SIM_write() family of functions (see the Simics Reference Manual description of SIM_write for a list of these), that text is written to stdout, and a call to each previously registered output handler is made. You can register new output handlers using the SIM_add_output_handler() function. Here is a pseudo-code example of how a module could get Simics to write a copy of all its text output to a log file: static void output_handler(void *file, const void *buf, size_t count) { fwrite(buf, 1, count, (FILE *)file); } static void init_local(void) { SIM_add_output_handler(output_handler, (void *)fopen("my-log.txt", "w+")); }

142

18.8. Using Threads in Simics Modules

18.8

Using Threads in Simics Modules

It is possible to write modules for Simics that use POSIX threads. Simics API functions can only be called from the main Simics thread though. For another thread to get control of the main thread, it can call the only thread-safe Simics API function SIM_thread_safe_ callback(). This function will install a callback that Simics main thread will call as soon as possible, even if Simics is at prompt waiting for a command input. When the user-installed callback is run, it is executed in the main Simics thread, and it is safe to call API functions from there. Another thread in the module may at this time also call API functions, if it syncronizes correctly with the callback function. Some support functions for C/C++ programmers, that are not really part of the Simics API, are also safe to call from a thread. This includes the vtprintf() family of functions, such as pr(), and also the vtmem malloc routines.

143

18.8. Using Threads in Simics Modules

144

Chapter 19

Adding New CLI Commands 19.1

Introduction

Commands in Simics are written in Python, and they access the internal state of Simics by using the Simics API, or by accessing configuration objects and their attributes. Since modules cannot add functions to the Simics API, all commands for devices and extensions use the configuration system. There are several benefits of using Python to define commands: The C/C++ code is forced to export much of its state, allowing other script users to access it. The module can be distributed in binary form, while the Python commands are still available with source, allowing a user to change them in a way he or she prefers. The source file with commands should reside in the same directory as the other source code for the module, and must be called commands.py. When the module is compiled, this source file is copied to the [simics]/host/lib/python-target directory, e.g. [simics]/x86-linux/lib/python-v9/. The resulting file will get the name mod_module-name_commands.py with any dash (-) characters replaced with underscore (_). The command file is automatically loaded into the Python environment in Simics when the module is loaded. It is also possible to explicitly load a command file: @from mod_trace_commands.py import *

19.2 Example of a new command This is an example on how to add a command in Python, as it would appear in the commands.py file of a module’s source code subdirectory: # this line imports definitions needed below from cli import * # this is my Python function that will be called when the 145

19.2. Example of a new command

# command is invoked from the Simics prompt. def my_command_fun(integer, string, flag): print "My integer: %d" % integer print "My string: %s" % string print "Flag is", if flag: print "given" else: print "not given" return integer # register our new command new_command("my-command", my_command_fun, args = [arg(int_t, "arg", "?", 10), arg(str_t, "name"), arg(flag_t, "-f")], alias = "mc", type = "my-module-commands", short = "my command does it", doc_items = [("NOTE", "This command is best"), ("SEE ALSO", "my_other_command")], doc = """ my-command is best. This is its documentation. arg is the first argument...""") The code above will define a command called my-command. When the command is invoked from the Simics command line interface, the function my_command_fun() will be called. The function must take exactly as many arguments as the command; in this case 3: an integer, a string, and a flag. The first argument is called “arg” and is optional, indicated by "?". If omitted by the user, the command function will be called with the default value, 10. The second argument is called “name” and is required (since there is no "?", there is no default value). The last argument is a flag and will have a value of 1 if the flag is given, otherwise 0. Flags are thus always optional. If the command function returns a value (a string or an integer) Simics will print this value on the terminal or pass it on to other commands as input arguments, e.g., print -x (my-command 15 foo). Writing help my-command at the Simics prompt will display: NAME my-command - my command does it SYNOPSIS my-command [arg] name [-f] ALIAS mc DESCRIPTION my-command is best. This is its documentation. arg is the first argument. NOTE This command is best

146

19.2. Example of a new command

SEE ALSO my_other_command

The command can be invoked in different ways, here are some examples: simics> my-command 2 foo -f My integer: 2 My string: foo Flag is given 2 simics> my-command bar My integer: 10 My string: bar Flag is not given 10 simics> my-command 20 -f Argument error: argument number 2 is missing in ’my-command’, string expected. SYNOPSIS: my-command [arg] name [-f] simics> print -x (mc -f name="hello there!" arg = 23) My integer: 23 My string: hello there! Flag is given 0x17

In the last case the alias is used and the command is passed to the print command that outputs the value in hexadecimal notation. All the parameters of the new_command() function will be explained bellow. After the parameter name follows the type of the parameter and if the argument is required, recommended, or optional: name — string (required) First argument (no need to write name =) and the name of the command. May include digits and underscores as well as dashes. Must begin with an letter. fun — function (required) The command handler function that will be called when the command is executed. The number of arguments must match the args-list(see below). Since new_ command is executed when the commands.py file is loaded into Python the function must be defined before the new_command call, as in the example. args — list of argument specifiers (required) This is a list of the arguments given to the command, and must match the arguments of the function described above. An argument specifier is created by calling the function arg(). This function takes as arguments a type (this is in fact also a function), that is called to handle the argument. Examples of available types are int_t, str_t, addr_t, filename_t(), and flag_t. See the next section for a discussion of these. To create an argument list of an integer and a string, use: ..., args = [arg(int_t), arg(str_t)], ...

147

19.2. Example of a new command

It is, however, recommended that names for the parameters are specified. This is done as a second argument for arg: ..., args = [arg(int_t, "value"), arg(str_t, "file")], ... This way the documentation of the argument list (help command) will use these names and also makes it possible to enter the argument in any order at the command line, e.g., command file = "/tmp/bar" value = 17 The flag type requires the name to be specified and the name must begin with a hyphen, e.g., “–all”. The corresponding value passed to the command handler function will be 1 if the flag is given on the command line or 0 otherwise. The addr type can be used for addresses. It understands argument of the form p:0xcf00 (physical address), v:0xff00 (virtual address), or 0xffdc at the command line. The command handler function will receive a tuple of the prefix and the address, e.g., ("v", 0xcff0). If only the address is given, "v" will be used. Sometimes it is convenient to have other arguments than flags optional. To indicate this, add "?" as the third argument to arg(), and the default value as the fourth; e.g., ..., args = [arg(int_t, "value", "?", 1), arg(str_t, "file")], ... makes value an optional argument with 1 as its default value. There are more arguments to arg: ..., args = [arg(str_t, "cpu", expander = exp_fun, is_a = test_fun)], ... will connect a tab expander for the cpu arg, i.e., the function exp_fun() will be called when the user hits tab upon entering the argument value. The expander function takes an argument representing the text the user has written for the argument. For example, if the user presses tab after typing command cpu = ultr, the exp_fun() will be passed "ultr" and should return a list of strings completing "ultr". Here is an example of an expander function: def exp_fun(comp): return get_completions(comp, ["ultraI", "ultraII", "ultraIII", "pentium"]) When called with "ultr", it will return ["ultraI", "ultraII", "ultraIII"]. The get_completions function filters the list and keep elements with prefix comp. The expander functions only works for the string type for the moment. 148

19.2. Example of a new command The is_a argument takes a function that tests if the argument is a valid one. It should return 1 for valid values and 0 otherwise. For example the read-reg command has as first argument a CPU (optional) and as second argument a register. If a user types read-reg g7, CLI will incorrectly interpret g7 as a CPU since g7 is a valid string and the command will fail. The is_a function could therefore return 0 for non-CPUs and pass the string to the next argument, which will match since g7 is a register. Polyvalue A command argument can be of multiple types as well (polyvalues). For example, ..., args = [ arg((str_t, int_t, flag_t), ("cpu","value","-all"), "?", (int_t, 0, "value"), expander = (exp1, exp2, None)) ], ...

will create an argument that is either a string, an integer, or a flag. The argument passed to the command handler function is a tuple specifying the arg-type, the value, and the name of the argument. E.g., command foo will pass (str_t, "foo", "cpu") to the command handler function. This is why the default value looks the way it does. The corresponding expander function will also be used. command cpu = abc will use the exp1 expander. doc — string (required if not doc_with is used) This is the documentation of the command. Some simple formatting codes can be used, such as , and for italic, bold and line-break. A blank line separates paragraphs. Italic does not usually work in terminals so underline will be used instead. Use italic to refer to arguments and bold for command names. type — string (default is “misc-commands”) This is the command category that the command belongs to. All categories will be listed when the help command is used. help category will list all command in that category. Any whitespace within this string will be replaced with dashes. short — string (recommended) A short description of the command used when listing commands, e.g. help –all). repeat — function (optional) If such a function is supplied, it will be called when the user enters an empty line (i.e., just presses enter) after this command has been run. The arguments passed to the reapeat function will be the same as those of fun (see above). This is used to implement the behavior of commands like disassemble, where pressing enter after having run one disassemble command disassembles the instructions following the last one of the previous command. namespace — string (optional) Makes the command a namespace command. Such commands are invoked as a method call of the form object.command, e.g., rec0.playback-start. This means that the command handler function will get the namespace object as first 149

19.3. Argument Types

argument (a recorder object) and then the rest of the arguments. The namespace string is either the class name of the object, e.g., "recorder", or the name of a “superclass” of the object, or an interface that the object implements. For instance, the class name “processor” is a superclass of any processor, e.g., “ultrasparc-ii”, and “breakpoint” is an interface that a memory-space object implements. The full name of a namespace command will be .command (angle brackets included) and this is what is printed when command are listed, but as stated above the command is invoked with object.command. Device commands are typically implemented using namespace commands. This is because they usually operate on a single configuration object, e.g., a MMU or cache object. doc_with — string (optional) This argument can be specified if a command should be documented together with another one. For example the disable command is documented with the enable command since they are tightly coupled together. So the doc argument is missing for the disable command and all documentation is written in the enable command. Note: doc_with together with a namespace command must be given as “.command” alias — string or list of strings (optional) Specify aliases for this command. Does not work with namespace commands. infix — 0,1 (default 0) Indicates that the command should be an infix command. For example the arithmetic command sets this argument to 1. pri — integer (default is 0) Sets the priority for the commands, typically only relevant to infix commands. For example, ∗ has higher priority than + (200 and 100, respectively). left — 0,1 (default 0) If the command is left associative or not (right associative).

19.3

Argument Types

Following is a list of the available argument types. Note that some of them are “real” arguments, while some are generator functions which, when called with appropriate parameters, return an actual argument.

addr_t Accepts a target machine address, optionally with an address space prefix, such as v: for virtual addresses or p: for physical. 150

19.3. Argument Types

filename_t(dirs = 0, exist = 0, simpath = 0) Generator function for filename arguments. If the dirs argument is zero (which is default), no directories will be accepted. The exist flag, when set, forces the file to actually exist. If simpath is true, files will be checked for existence using SIM_lookup_file(), searching the Simics search path. simpath implies exist. On Windows, if Cygwin path conversion is performed (see SIM_native_path() for details), the filename will be converted to host native format.

float_t Accepts floating-point numbers.

int32_t Accepts any integer that fits in 32 bits (signed or unsigned). The value passed to the command function is cast into an unsigned value.

int64_t Accepts any integer that fits in 64 bits (signed or unsigned). The value passed to the command function is the value cast to unsigned.

int_t Accepts any integer (regardless of size).

integer_t Accepts any integer that fits in 64 bits (signed or unsigned). Corresponds to the Simics API’s integer_t.

range_t(min, max, desc, positive = 0) Returns an argument which accepts any integers x, such that min 6 x 6 max. desc is the string returned as a description of the argument. If positive is true, any negative values will be “cast” into positive ones using the formula max + v + 1, where v is the negative value.

sint32_t Accepts any signed integer that fits in 32 bits.

sint64_t Accepts any signed integer that fits in 64 bits. 151

19.3. Argument Types

str_t Accepts any one word or quoted string.

uint32_t Accepts any unsigned integer that fits in 32 bits.

uint64_t Accepts any unsigned integer that fits in 64 bits.

152

Chapter 20

Creating a Device Step by Step Simics is distributed with a device template that can be used when writing a new device module. The following files are located in the directory simics/src/devices/ empty-device. • Makefile — makefile for the device • empty-device.c — device source code in C • commands.py — device commands in Python The template files contain about 15 USER-TODO comments that mark places where additions to the source code should be made. Following are the most important steps when creating a new device: • Copy the full directory empty-device to a new directory for your device. Example: sh$ cd simics/src/devices/ sh$ cp -r empty-device foo-device sh$ cd foo-device sh$ mv empty-device.c foo.c By convention devices should have as detailed names as possible, to avoid confusion and name conflicts. • Edit the Makefile to reflect the name of the new device, source code file and its directory. • Add the module to the simics/config/modules.list file. There is already an entry there for the empty-device that can be copied and modified. • Open the C source code file, and look for the USER-TODO comments. The following steps will describe some of them. To make the source code clearer, it is a good idea to change the name of all empty_ functions and types to match the new device name. 153

• Set the DEVICE_NAME define to the name that the device should have in Simics. • Add code to the function empty_operation(). This function will be called each time the cpu (or some other device) accesses any mapped range of this device. • Change the example value attribute to real attributes needed for your device. Different kinds of attributes are described in the Configuration section of this manual, and in the Reference manual. • Extend the info command in commands.py to print better information about your device. Use the attributes to query the device about its status. For static read-only data use pseudo attributes. • Add any other commands to the commands.py file. To trigger actions in the device, pseudo attributes are often used. • If you haven’t tried to compile your device module yet, it is probably a good idea to do that now. Example: # cd simics//lib # gmake foo-device Creating dependencies: /home2/am/simics/src/devices/foo-device/foo-device.c === Building module "foo-device" === Building version.c Compiling foo-device.c OK! Compiling module_id.c Linking /home2/am/simics/x86-linux/lib/libfoo-device-32.so Creating dependencies: /home2/am/simics/src/devices/foo-device/foo-device.c === Building module "foo-device" === Building version.c Compiling foo-device.c OK! Compiling module_id.c Linking /home2/am/simics/x86-linux/lib/libfoo-device-64.so

The module_id.c is a file that is automatically added by the build environment. • Once the module is compiled, it’s time to add it to the configuration file. The example below will create an object and map it into memory. OBJECT foo2 TYPE foo-device { value: 5 # optional attribute } OBJECT phys_mem0 TYPE memory-space { map: ((0x00000000000, memory0, 0x0, 0, 0x20000000), snip (0x1c400006000, foo2, 0x0, 0, 0x100), snip }

154

• ADVANCED: Make sure that the Required and Optional attributes in the device can be used to support checkpointing. • ADVANCED: Use the malloc macros defined by VTMEM. This will help you debug any problems with dynamic memory handling. • ADVANCED: If the module reads external input in some way and does not use any supplied Simics services for it, send all input data through the recorder module. This will allow simulation sessions to be recorded and later run again with identical behaviour.

155

156

Chapter 21

Creating a Timing Model A timing model in Simics is essentially a piece of code that hooks into Simics’ memory system and tells the simulator core how long time a memory operation will take. The timing model installs a callback function which is called on every memory operation that misses in the STC (see section 16.5). This callback function can, e.g., be used to gather information about memory usage, set memory access times, or implement complete cache models. Simics includes source code for two modules that implement timing models. The sample-memhier extension catches all memory operations and writes them to a log file. It doesn’t cause any memory operations to stall (by always returning zero as the stall time). The sample-cache extension implements a simple model of a single or multiple level memory cache and is able to stall memory operations when cache misses occur. These two examples can be used as a base if you are going to implement your own timing model. Note: Most information related to stalling in this chapter applies to memory operations initiated by a CPU. Only a few devices (e.g. some SCSI controllers) generates memory transactions by their own, and these device models usually don’t support stalling. As mentioned in chapter 15, you typically attach your timing model to an object of the memory-space class using its timing_model attribute: OBJECT phys_mem0 TYPE memory-space { map: (...) timing_model: my-timing-obj } OBJECT my-timing-obj TYPE my-timing-model { } This will cause any memory operations passing through the phys_mem0 memory 157

21.1. The Operate Function space to call the operate() function in the my-timing-model class’ timing-model interface. Such an interface must be exported by the class, which is done by a call to SIM_register_interface(). The following pseudo code shows how this can be done: static cycles_t my_timing_model_operate(conf_object_t conf_object_t map_list_t memory_transaction_t

*mem_hier, *mem_space, *map_list, *mem_op);

static void INIT_FUNC(void) { class_data_t *class; timing_model_interface iface; class = SIM_register_class(); iface.operate = my_timing_model_operate; SIM_register_interface(class, TIMING_MODEL_INTERFACE, &iface); }

21.1

The Operate Function

The operate() function in the timing-model interface takes four arguments: conf_object_t *mem_hier This points to the timing model object, i.e., my-timing-obj in our example above. conf_object_t *mem_space The mem_space argument is the memory space object in which the timing model has been inserted (via the timing_model attribute in the memory space). map_list_t *map_list The map_list argument describes the actual entry in the map attribute list that this memory operation matched (as returned from a call to the space_lookup function in the lookup interface). memory_transaction_t *mem_op This is a pointer to information about the actual memory operation. The memory_ transaction_t and the generic_transaction_t (which is a generalization of the former) data structures are explained in detail in the Simics API Data Types section of the API chapter in the Simics Reference Manual. Note that there are a few limitations on what may be done with a memory operation inside the operate() method; e.g., one may return a (non-zero) stall time only if the may_ stall bit in the mem_op is set. Details about such limitations can be found in the Simics Reference Manual (see above). 158

21.2. Observing Instruction Fetches The return value of the operate() function is the number of cycles to stall the cpu before returning the result from the memory operation. A return value of zero means that the operation has finished. If a non-zero value is returned, the cpu will be stalled that many cycles, and then a new call to the operate() method will be done. This second call can, again, return a non-zero value if desired. This is repeated until zero is returned.

21.2

Observing Instruction Fetches

By default, instruction fetches won’t be seen by the timing-model. In order to see them too, you will have to change the current instruction profiling mode. Refer to section 15.4 for more information.

21.3

Changing the Result of Memory Operations

If you want to see the value or change the result of a memory operation, you can’t use the timing_model attribute. Instead, you have to register the snoop-memory interface and attach your object to the snoop_device attribute in the memory space. The layout of the snoop-memory interface and the timing-model interface are actually identical; i.e., they share the timing_model_interface_t data structure. The operate() method in the object indicated by the snoop_device attribute in a memory space is called after the memory load or store has finished (i.e., after any timingmodel returned zero stall time). This lets you call the SIM_get_mem_op_value() or SIM_set_mem_op_value_buf() functions to read or modify the actual data the memory operation will report to the initiator of the operation (be it a cpu instruction or a device). It is not allowed to return non-zero stall time from the operate method of a snoop_ device. Any stalling has to be controlled from a timing_model.

21.4

Chaining Timing Models

Sometimes it is desirable to chain timing models, e.g., if you’re implementing a multilevel cache model and want to model each level of the cache as an individual class. To do this, the operate() function must call the corresponding functions of the lower levels (a lower or next level cache is, for the rest of this section, considered to be further away from the CPU, closer to the actual memory). The sample-cache source code included with Simics is an example of how to do this. Whenever there is a miss in the cache, the sample-cache object creates a new memory operation and calls the operate() method of the timing-model interface from the next level cache specified by the timing_model attribute. Note that the next level cache’s operate function might return a non-zero stall time, which the sample-cache has to return back up to its caller. The caller will then call the sample-cache’s operate method again after that stall time has passed. The sample-cache then has to call the next cache level’s operate function again. This is repeated until the return value from the next level cache is zero. 159

21.4. Chaining Timing Models

Note also that the memory transaction passed on to the next level cache is different from the one that the first level cache received. This is because we’re actually fetching the whole cache line that the original operation missed in and we’re actually interested in looking at the data the next level returns. This allows us to investigate cache incoherencies, but depending on what your particular needs are, this may or may not be desirable. It might be that it’s perfectly enough to call the next level’s operate function with the same memory operation we received.

160

Chapter 22

Creating a Cache Model 22.1

Using the Sample Cache Code

Sample-cache is a simple cache model with the following features: • Multiple oustanding transactions support • Configurable number of lines, line size, associativity • Multi-level • Write-through, write-allocate • Physically tagged and indexed • Random replacement policy Contrary to generic-cache, sample-cache has been kept deliberately simple with a few number of features. It is a good example of a simple cache model exploiting Simics possibilities, and probably a good starting point if you want to write a cache-model. The source code is heavily documented to allow you to get into the model easily.

22.2

Using the Generic Cache Code

The generic cache code included with Simics can be used to design your own caches. How to do this is demonstrated in the generic-cache.c source file. In short, you first define some basic characteristics of the cache, like the number of lines, associativity, virtual or physical indexing, write allocate policy etc. Many parameters can be left undefined and will then become runtime configurable using cache attributes. However, if you know that you only want to simulate, for example, a direct mapped cache it is better to hardcode this since this will make the code faster. Some parameters, like the number of sublines per cache line, can only be configured at compile time. 161

22.2. Using the Generic Cache Code

After having defined your cache parameters you include gc-common.h and gcinline.c (also found in the generic-cache directory) which will generate code depending on the defined parameters. Special functionality can be added by defining hook functions that will be called for different events, such as write misses, or a cache line replacements. This should work quite well for most normal caches, but if you are simulating an exotic cache system it might be a better idea to change the code in gcinline.c directly, or even rewrite it from scratch.

162

Index Symbols

limitations, 106 multiple levels caches, 102 sample-cache, 157, 159 simulation, 101 source code, 161 statistics, 107 callback, 41, 66 cd, 46 CD-ROM, 75 cd-rom image files, 75 checkpoint, 24, 41, 57 class, 128 delete_instance, 130 kind, 130 new_instance, 130 register, 130 colorized make disabling, 121 command line interface, 41, 47 accessing commands from Python, 62 adding commands, 145 argument resolving, 48 commands, 46 expression, 49 help system, 49 namespace commands, 48 operators, 49 remote frontend, 51 tab completion, 51 variable, 49 commands adding, 145 namespace, 48 configuration, 41, 55, 127

%, 45

A adding command, 145 address space, 42, 85 api-apropos, 65 api-help, 65 apropos, 51 ARP, 31 attr_value_t, 133 attribute, 55, 128, 133 indexed, 136, 139 pseudo, 135 register, 137 simple, 134 slice, 137 structure, 133 type, 138

B BOOTP, 98 breakpoint, 81 control register access, 82 I/O, 82 memory, 81 symbolic, 88 temporal, 82 build environment, 119

C c, 45 c-utils.h, 141 caches generic-cache, 101 id-splitter, 104 163

INDEX

access from Python, 60 attribute, 55 object, 55, 60 scripted, 61 connecting to a real network, 95 connecting to simics central, 94 context, 85 current, 85 tracking, 90 continue, 45 Core_Initial_Configuration, 128 craff, 41, 79 current context, 85 cycle, 41

eval_cli_line, 62 event, 42, 115 example-device, 153 extension, 42

D

GCC, 88 GDB, 83 gdb-remote, 83 generic-cache, 101 limitations, 106 statistics, 107 get, 45 global.h, 141 gmake, 119 GNU make, 119

F fini_local, 127 flexlm, 17 floppy, 76 images, 76 Forte C compiler, 89 frame, 87

G

date, 46 debug information, 88 debugging, 83, 85 memory spaces, 89 remote, 83 scripted, 90 shared libraries, 84 symbolic, 83, 85 device, 41 DHCP, 31, 98 dirs, 46 disks, 69 building from multiple files, 74 cd-rom images, 75 copying real, 72 floppy, 76 getting disk images, 22 getting disk images, 20 host CD-ROM, 75 images in craff format, 79 loopback mounting, 77 MBR, 74 display, 46 DNS, 31, 98 down, 87

H hap, 42, 66 help system, 49 documenting commands, 149 host-cdrom, 75 hostfs, 42, 78

I id-splitter, 104 init_local, 127 installation disk images, 20, 22 license server, 17 multiple users, 19 interface register, 139 ITIMER_REAL, 141

E echo, 46 ELF, 88 ethernet-central, 31, 93, 95, 97

L license 164

INDEX

P

floating, 17 license server, 17 Linux kernel, 86 list-failed-modules, 46 list-modules, 46 load-module, 46 loopback mounting, 77 ls, 46

pfregs, 45 plain-symbols, 89 popd, 46 pos, 88 pr, 143 pregs, 45 print, 46 printf, 142 pselect, 45 psym, 87 ptime, 45 pushd, 46 pwd, 46 Python, 42, 59, 90

M magic breakpoint, 67 magic instruction, 67 malloc, 141 memory mappings, 84 memory-space, 157 module, 42, 119, 127 build environment, 119 commands, 46 compilation, 121 delayed initialization, 127 example, 140 fini_local, 127 header files, 141 init_local, 127, 131 Makefile, 121, 131 signals, 141 user version, 125

R RARP, 98 read-configuration, 25, 57 read-reg, 45 remote frontend, 51 run-command-file, 46 run-python-file, 46, 60

S SA_RESTART, 141 sample-memhier, 157 sc, 45 script, 27, 59 commands, 46 script branch, 62 set, 45 setitimer, 141 si, 45 sigaction, 141 signals, 141 SIM_add_output_handler, 142 SIM_BC_NO_STDOUT_REDEFINE, 142 SIM_get_attribute, 128 SIM_get_interface, 139 SIM_log_constructor, 132 SIM_new_object, 140 SIM_register_attribute, 137 SIM_register_class, 130 SIM_register_interface, 139, 158

N namespace, 50 commands, 48 new_command, 145 nm output format, 89

O object, 128, 131 create, 140 declaration, 131 delete_instance, 130 new_instance, 130, 132 operate timing_model_interface function, 158 operators precedence, 49 165

INDEX

SIM_set_attribute, 128 SIM_step_clean, 141 SIM_step_next_occurence, 141 SIM_step_post, 141 SIM_time_clean, 141 SIM_time_next_occurence, 141 SIM_time_post, 140 SIM_write, 142 Simics Central, 31, 34, 44, 93 simics central connecting to, 94 connecting to real network, 95 routing table, 97 simics_api.h, 141 simmalloc.h, 141 snoop device, 159 stabs, 88 stack frame, 87 stack trace, 86 stalling, 115, 157 STC, 42, 116, 157 stdout, 142 step, 42 step queue, 115 step-cycle, 45 stepi, 45 Sun Workshop C compiler, 89 sym, 87 symbols loading, 88, 89 symtable, 85 system calls restartable, 141

up, 87 user version modules, 125 USER_VERSION, 125

V VTMEM, 141

W watchpoint, 88 whereis, 88 write-configuration, 24, 57 write-reg, 45

X x, 45

T tab completion, 51 TFTP, 99 threads, 143 time queue, 115 timing model, 102, 157 chaining, 159 trace, 26, 27

U undisplay, 46 166

View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF