You are on page 1of 48

V IRTUTECH A PPLICATION N OTE

TEACHING HARDWARE-
SOFTWARE
INTEGRATION WITH
SIMICS

VERSION 0.9.5
JAKOB ENGBLOM

WWW.VIRTUTECH.COM
T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

INTRODUCTION
This application note documents a teaching setup for Virtutech Simics
intended to teach hardware-software integration at a system level. The
setup consists of an MPC8641D-based virtual platform, running Linux,
into which students add a custom hardware unit, a Linux driver for the
hardware unit, and user-level software that makes use of the custom
hardware unit.

The setup consists of the following pieces:

• The target machine itself, an MPC8641D virtual platform. The


version used is mpc8641d-simple in Simics 4.0.
• U-Boot version 1.3.0 for booting the target machine.
• A Linux kernel version 2.6.23, configured for the target machine.
• A ramdisk-based target file system containing a Busybox version
1.12.1 setup.
• An example Simics “simple_device” device model.
• A Linux char driver for “simple_device”, configured to be built as
a loadable kernel module.
• A test program activating the simple device over the device driver.
• Simics scripts to automate the loading of software and hardware
into the virtual target platform.
• A cross-compiler for building target software, kernel, busybox, and
u-boot.
• An example target application for which to create hardware
acceleration. Currently, this is a “rule30” cellular automaton
implemented in C.

PROJECT IDEAS
The following is a set of suggested projects that can be done using this
setup, teaching various aspects of hardware-software integration.

Designing a Hardware Accelerator


Students should use the simple_device and its driver as the starting point for
the creation of a memory-mapped device that accelerates the execution of
the target application “rule30” (or some other application of choice).

The memory-mapped device should be created at the default Simics


transaction-level of detail. Timing should be handled by assuming or
prescribing some kind of delay from when data is entered until it is

Page 2 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

produced (as part of the evaluation of the design, students might try
different delays in order to determine how fast the hardware must be to be
worthwhile).

The students would not expected to actually design concrete hardware


circuits to implement the functionality in the hardware accelerator; rather
the focus is on the interface between the hardware and the software, and
the interaction low-level and user-level software.

The students should measure the performance impact of their hardware


accelerator using the simple timing provided by Simics, for example
counting the time to compute benchmarks and the number of instructions
required.

It is quite possible that the overhead of a device driver cancels a large part
of the benefit of acceleration hardware. Exploring that aspect is part of the
mission here.

Measuring Impact of Driver Style


This is a lab that can be done as part of the custom hardware accelerator,
but also is useful on its own as small lab. Basically, measure the
performance of alternative solutions to interfacing a device driver to
software. In particular, comparing using mmap(), single-word write(), and
large block write(). Completion checking could also be done by using
polling and non-blocking read(), polling mmap(), or a blocking read().

Understanding hardware-software integration


For a smaller lab, the setup can be used to have students add some small
feature or register to the device, and do the necessary adjustments to the
device driver and application program to use the new feature. This is a
good way to show how hardware and software interacts, in a lab that
should not take many hours to do.

Teaching Linux Device Drivers


Given the test program and simple device, the device driver could be
removed, and students asked to implement the device driver given the
usage in the test program and the defined hardware interface. The Simics
setup provides very good support for experimenting with device driver
development, as it provides a safe system that can always be reset no
matter what happens. It also provides nice insight into the hardware and
software behavior to help debug the device driver.

Page 3 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Teaching Virtual Platform Modeling


The setup could also to teach hardware modeling for virtual platforms.
Students might be given the specification for some real block in the
MPC8641D, and tasked with implementing a functional model for the
block. With complete driver code in source, debugging the hardware-
software interface and understanding the requirements of the software is
greatly facilitated. The example simple_device is really too simple to be
useful for this purpose, the students should work on some real hardware
component.

AVAILABILITY
The software setup will be made available from Virtutech as a
downloadable archive. It should be noted that it is fairly extensive, since it
includes source code for all relevant components. The complete file
archive is on the order of 1 GB.

Host Machine
The setup requires a Linux host, due to the need to cross-compile the
Linux kernel and related software, it is very hard to port to Windows in a
reasonable way. It has been tested on a Kubuntu 7.04 setup.

Host Compiler
The host machine needs to have the tools available to build Simics
modules, which means that it needs to have a host C compiler installed.
Please refer to the Simics installation guide for more information.

Simics Installation
Virtutech Simics is supposed to be installed in the default way, which
would put it at /opt/virtutech/simics-4.0/. This does not matter once
workspace setup for the Simics workspace has been performed. All work
is done in the user workspace.

The Simics installation needs to at least have the following packages


installed:

• Simics base 4.0.x


• Simics model builder 4.0.x
• Simics MPC8641D-simple 4.0.x

Please refer to the Simics installation guide for more information on how
to install packages.

Page 4 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

OVERVIEW
The complete setup is fairly complex, as shown in Figure 1, but the course
focus is just on three parts, all the other parts are really just scaffolding
necessary to provide a realistic system environment:

ƒ The device being developed


ƒ The device driver for the device
ƒ The program using the device via the device driver

Figure 1. The complete virtual system setup

Virtual MPC8641D Board

MPC8641D SoC
Simics 
scripting Program using  Other
Busybox
simple device program

Device 
Simple device  Simicsfs
Virtual serial  drivers
driver driver
console
UART Linux 2.6.23 kernel
CPU cores 0 and 1
Ethernet
Virtual 
network
MemCtrl Timers MPIC
RAM Simple_device Hfs device
PCI PCIe

Simics
Host file 
Host operating system system

Host computer
Host disk

The areas of primary interest for teaching are shown with bold outlines in
Figure 1. In all likelihood, the virtual network will not be used, but it is
there if needed. The simicsfs file system provides an easy way to get
software and data into the target machine, without having to rebuild the
initial ramdisk file system (which is easy with the provided scripts, but
fairly time-consuming anyway).

Page 5 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

All compilation of software for the target will be done outside of the
Simics target machine, using cross-compilation tools. This is how most
embedded software is developed in practice today.

DIRECTORY LAYOUT
The setup contains a complete embedded system, and as such it is fairly
complex. The file set is supposed to be put in some main directory, which
we call base in the following discussion.

The relevant directories in base are shown in Figure 2.

Figure 2. Directories in the base directory


ƒ base/cross-compiler/ -- the cross-compiler to be used to compile all code
ƒ base/documentation/ -- documentation about the target machine and Simics.
ƒ base/initrd-busybox/ -- the ramdisk construction and busybox build environment. The top-
level contains the files needed to build and modify the ramdisk (initrd).
ƒ base/initrd-busybox/busybox-1.12.1/ – the build environment for the busybox binary
ƒ base/linux-kernel/linux-2.6.23/ – the Linux kernel build area
ƒ base/linux-kernel/linux-2.6.23/drivers/char/simple_example_driver – our example
driver for the simple device
ƒ base/linux-kernel/linux-2.6.23/fs/simicsfs – the Simicsfs file system driver that
allows the target Linux system to mount the host file system. You should not need
to care about this, but it is good to know that it exists.
ƒ base/simics-workspace/ – the Simics 4.0 workspace used to run Simics and build models.
ƒ base/simics-workspace/modules/simple_device/ – the source code for the simple
device model
ƒ base/simics-workspace/targets/mpc8641-simple/ – the scripts to run and start the
MPC8641D machine used in this setup, as well as scripts to load new hardware
and drivers and test software onto the machine
ƒ base/simics-workspace/targets/mpc8641-simple/images/ – the bootable U-Boot and
Linux and initrd images.
ƒ base/simics-workspace/targets/mpc8641-simple/target-code/ – here is where target
code is located and built
ƒ base/simics-workspace/targets/mpc8641-simple/target-code/simple_device_test/ – a
test program that uses the Linux driver to use the simple example device
ƒ base/simics-workspace/targets/mpc8641-simple/target-code/rule30/ – one example of
a program for which to design a hardware accelerator
ƒ base/u-boot/u-boot-1.3.0/ – the U-Boot build setup

Figure 3 shows a screenshot of a file browser looking at the file structure.

Page 6 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Figure 3. Browsing the file structure

HOST ENVIRONMENT VARIABLES


To use the provided software with minimum hassle, please add the
following definitions to your logon file, like .bashrc:

Figure 4. Environment Variable Setup


## Assume that the HSI file structure is under ~/
export ARCH=powerpc
export CROSS_COMPILE=~/cross-compiler/powerpc-linux-gnu/bin/powerpc-linux-gnu-
export PATH=$PATH:~/u-boot/u-boot-1.3.0/tools/

The paths might of course be different on your machine. The path to the
cross-compiler is automatically picked up from the environment variable
by all parts that need to use it.

Page 7 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

RUNNING SIMICS
To give a feel for how things work with this setup, we should start by
running Simics with some scripts.

On a Linux host, Simics is easiest to start using scripts provided in the


simics-workspace. To start Simics in GUI mode, do the following:

Figure 5. Starting Simics in GUI mode

base$ cd simics-workspace

base/simics-workspace$ ./simics-gui &

Once the Simics GUI has started, you should then select “New Session from
Script…” and select a start script. We suggest you start with the script called
“mpc8641-simple/mpc8641-hsi-course-setup.simics”, as shown in Figure 6.

Figure 6. Starting a Simics simulation session from the GUI

Once this script has started, you will see a new window on the screen,
which is the serial console of the target machine. Nothing has appeared yet
there, since the simulation is not yet started. Figure 7 shows the state at
this point, and also identifies some key windows.

Page 8 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Figure 7. Simics has started a new simulation session

Press the start button in the GUI to start running the target. Note that you
can pause the simulation at any point in time and resume it.

If you wait a while, the target system will boot into U-Boot, load the
kernel and ramdisk into memory, boot the Linux kernel, mount the
ramdisk, and get to a login prompt.

The Simics command-line window will be issuing some warning about


bad accesses to various places in memory. This is completely normal, and
most of it is hardware probing where device drivers try various things to
see how the hardware reacts. Also, hardware is quite commonly very
forgiving about minor mistakes in accesses (such as attempting to change
the value of read-only bits in registers), while Simics presents warnings.
On physical hardware, these kinds of issues were never noticed, and the
drivers therefore have not been patched to correct them.

Page 9 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Simics has scripted the bootup and login process, and the boot will finish
with you logged into the Linux running on the virtual MPC8641D target.

You can try various simple commands as shown in Figure 8 to familiarize


yourself with the target system.

Figure 8. Example commands on target system

~ # cat /proc/interrupts
~ # ls /bin
~ # cat /proc/cpuinfo
~ # cat /proc/devices
~ # ls –l /dev
~ # ping 10.10.0.1
~ # df

Checkpoint and restore


A key feature of Simics is checkpointing. To try this, do the following:

ƒ Pause the simulation


ƒ Select “Save Checkpoint…” from the file menu, and save the
checkpoint anywhere you like.
ƒ Select “New Empty Session” from the file menu, which will remove
the current simulation.
ƒ Select “Open Checkpoint…” from the file menu, and select the
checkpoint you save previously.
ƒ You should now be back at the exact same place.

Note that there is already a checkpoint provided in the course materials


that is used by other scripts to start simulation from the point where the
target system is booted.

Reverse execution
Another interesting Simics feature is reverse execution. To try this, do the
following:

ƒ Enable reverse execution by clicking the right-most button in control


window ( ). You should see “reverse execution enabled” in the
status bar.
ƒ Start simulation again.
ƒ In the target console, do something really destructive like “rm /bin/*”.
Let this run its course, and note that the system becomes pretty
broken. Nothing works.

Page 10 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Figure 9. Breaking the target system

ƒ Stop the simulation and click the reverse button.


ƒ Simics will now run the action backwards.
ƒ You can click forward to replay it.
ƒ To actually do something different, reverse back to the state before
the rm command, and then select “Clear Input Recording” from the Run
menu. This will make Simics forget all you did, and you can now do
something different.

Note that Simics does not save the changes you make to the target system
disk, so there is no risk that you can wreck future runs by making mistakes
inside a simulation run. The reason for this is both that you need to
explicitly ask Simics to save any changes to target system disks in order
keep them (and they would only be saved as disk differences from the
original state), and that the kind of initial ramdisk disk used in this setup
cannot be saved. It is loaded into memory and uncompressed during the
boot, and its state in ram is not possible to compress back down to a file
system for future reference.

Page 11 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Simicsfs host disk access


The target system we are using has been configured with a special Simics
feature that allows the target Linux to access the disk on the host machine.
This is very handy to copy code and data into the target.

To try this, start Simics from the script “mpc8641-hsi-course-booted.simics”,


which will open a checkpoint of a booted system. Then, in the target
console, do “mount /host” and then “ls” to see the host file system.

If you want to change where the starting point for the simicsfs file system
on the host file system is, you need to use the Simics command-line
window and the command “hfs.root”.

Figure 10 shows an example session using simicsfs.

Page 12 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Figure 10. Use of simicfs to mount the host

Once you have copied the files you need into the target system, you should
unmount the host file system using “umount /host”. The reason is that this
preserves the deterministic and repeatable semantics of Simics – mounting
the host introduces a non-controllable factor into the simulation.

Try a complete integrated test run


Simics has a very powerful script environment, and this is used in this
teaching setup to create short turn-around times. The most complete such
script is “hsi-course-booted-load-driver-and-test.simics”. Start a new
session using this script, and Simics will do the following:

ƒ Start from a checkpoint of a booted machine


ƒ Add in the simple_device device model
ƒ Mount the host and copy the driver code from the host
ƒ “insmod” the driver into the Linux kernel

Page 13 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

ƒ Create the /dev/ node needed to access the driver


ƒ Copy the test program from the host
ƒ Run the test program
ƒ Stop the simulation run

The script is shown in Figure 11. Note how it works by calling other
scripts, running the simulation for a while (using continue, the scripts
called will call stop to stop the simulation).

Figure 11. Script to run a complete test run

#
# Start from the checkpoint, and then load the driver,
# and then run the test program that exercises the driver
#
run-command-file "%script%/mpc8641d-hsi-course-booted.simics"

#
# Load the driver
# -- Provide argument here to give it an address
#
$insmod_arguments = "phys_addr=0xf80f0000"
run-command-file "%script%/hsi-course-load-driver.simics"
continue

#
# The load driver script finishes once the driver is loaded
#
run-command-file "%script%/hsi-course-load-test-program.simics"
continue

In this way, testing a new set of device model, device driver, and test
program is really very simple. There is no manual work involved other
than running the script.

Note that all of the steps above can be run from the Simics command-line
interactively.

For more on Simics scripting, please see the “Advanced Features of


Simics” document in the Simics documentation. In particular, look into
how to script the serial console and the use of script branches.

Page 14 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

THE SIMPLE_DEVICE MODEL


The simple_device is written in DML, the Virtutech Device Modeling
Language. As shown in Figure 12, DML is compiled into C code, which is
then compiled by a host C compiler into a dynamically loadable library
(shared object on Linux hosts) that can be loaded into the Simics
simulator.

Figure 12. DML compilation process

DMLmodel DML
source files templates
& library

User program

DML Compiler Target operating system

Target firmware

C files Simics
header files
IO,
Devices Links,
Devices Devices Devices
Devices
Devices Memories Processors
Inter-
connects
C Compiler

Simics target machine

Simics
module DLL

Since you will be using DML in this course, you should look into the
documentation provided about DML.

ƒ In the documentation directory, you will find a whitepaper on DML to


give an introduction.
ƒ There is also a whitepaper on modeling that presents the Simics
modeling philosophy in some detail.
ƒ After this, you should refer to the Simics documentation. To do this,
you can start Simics in GUI mode, and then refer to the help menu
(see below for how to start Simics, and Figure 13 for how this can
look). You can also find the documentation at /opt/virtutech/simics-
4.0/simics-model-builder-4.0.x/doc, for example in order to print it out.
The most important manuals are:
ƒ Modeling your System in Simics
ƒ DML 1.2 Reference Manual

Page 15 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Figure 13. Help from the Simics GUI

Building the Device Model


To rebuild the device model, you go to base/simics-workspace, and issue
“make”. Note that you do not need to go down into modules directory to do
this. Figure 14shows an example session in an xterm on Linux.

Page 16 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Figure 14. Building the Simics device model

Once the device model has been built, it can be loaded into Simics using
the script “hsi-course-add-simple-device.simics”. This script creates a new
device object in Simics and sets the crucial parameters for its integration
into Simics: the name of the processor it is attached to for simulation
purposes, and the target for its interrupts. Figure 15 shows the Simics
command-line code needed to create a device object and map into
memory. The line starting with “@” is inline Python code, which is often
used in Simics scripts to do complicated things.

Figure 15. Device mapping script

load-module simple_device
@SIM_create_object("simple_device","sd0",[["queue",conf.cpu0],["irq_dev",[
conf.pic,'internal_interrupts']],["irq_level",23], ["time_to_result", 1e-
3]])
ccsr_space.add-map sd0:regs 0xf0000 0x100

The device model in the target memory map


The device model is mapped into the target memory at address 0xf80f_0000
as seen from the processors. How this is done is shown in Figure 15. This
address is in the range of the on-chip simple peripherals of the MPC8641D

Page 17 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

SoC, and the device is Simics-technically mapped into a memory space


called “ccsr_space”, which is at offset 0xf800_0000 in the main physical
memory space map. Inside this space, it is located at 0xf_0000. There is
room until 0xf_ff00, where the pseudo-device for the simicsfs system is
mapped, which should be plenty of room for memory-mapped registers for
an accelerator.

Note that you can map into any other free location, there is nothing
mandatory about this. But it works. To see all mappings in Simics, use the
“Memory Mappings Browser” found on the “Tools” menu. Figure 16 shows
how this looks after the device has been mapped. Our simple device object
is called “sd0”, keeping with Simics style of using fairly short object
names, and the “:regs” bit indicates that the register bank in the device that
is being mapped here is called “regs”. Look inside the source code in
simple_device.dml and you will find the declaration of this register bank.

Page 18 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Figure 16. Memory map

To further look into the device, you can either look at the source code or
use the Simics “Device Registers” window you find on the “Debug” menu.
Actually, look at both and see how they relate. There is a also an “Object
Browser” available that presents the Simics implementation view of the
objects in the simulation, as shown in Figure 21.

Note that mapping has a defined length, and this is set in the script creating
the device, in the “map” command that maps it into ccsr_space as shown in
Figure 15.

Page 19 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Figure 17. Device register view

Interrupting the CPU


The simple device model is setup to generate interrupts to the processor
when an operation is complete. To do this, it currently uses interrupt
number 23 to the MPIC main interrupt controller. This is a number
borrowed from some unused on-chip devices, since the Linux kernel was
hard to convince to accept any IRQ number. Note that the Linux kernel
considers this to be IRQ 39, since the first 16 IRQ numbers are dedicated
to the external i8259 interrupt controller also found on the system.

You should not need to change this part of the device model or its setup.
Just use the facilities provided in the simple device code to raise and lower
interrupts. How to do this should be clear from the source code.

Understanding the device functionality


The simple device code is intended as a starting point for your own
accelerator device. Its current functionality is very simple: it performs a
configurable (using the control register) operation combining all values
written to its input register.

The result is put into the accumulator register.

The target software is expected to check the operation completed (OC) bit in
the status register before reading the results. This bit is set with a delay
from the last write to input (note that input accepts data at any rate). Only
after this delay has passed will the device model set the OC bit and send an
interrupt signaling completion.

Page 20 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Note that the result in this simple model is computed immediately, but that
it is not considered valid. You could also model this by not setting the
value of the accumulator register until the final result is due, but that would
require some kind of internal register to hold the result until then. This
type of simplified modeling works well most of the time, especially when
we know that the target software is well-behaved.

The delay is configured using the time_to_result attribute of the device


model, and is set from the Simics command-line (for experiments, you can
set it using the Simics command sd0->time_to_result = TIME at any point in
time from the command-line window),

The delay is implemented by using Simics events, posted into the future so
that the device model gets a callback to “event()” method inside the “event
operation_complete” object in the DML file.

The version register is used by the device driver to check that the device is
really what it expects and to report the version number of the device
hardware to the software.

The irq_num register is a bit of cheat, as it communicates the interrupt


configuration from the hardware device to the software driver, by peeking
at the system setup in Simics. In physical hardware, this might be hard to
do depending on the nature of the interrupt controller and system.

Device “info” and “status” commands


Simics has a very powerful command-line interpreter, which is fully
extendible by users like you. For the benefit of users, all devices are
supposed to implement two custom commands to expose its state and
setup.

These commands are defined in the file base/simics-


workspace/modules/simple_device/commands.py, which is a Python-language
source file. If you do not know Python, there is no reason to worry. It is a
very simple language to pick up if you know any language in the C family,
and the structure of the commands.py file makes it very simple to extend it.
Basically, what is done in the “info” and “status” commands is to read
values of attributes in your Simics device model, and present these to the
user with an explanatory text, and there is support for this in Simics core.
All you supply is a list of heading-attribute name pairs.

The output is viewed both in the Simics object browser (as shown in
Figure 18), and from the command-line using sd0.info/sd0.status
commands. Note that there is no static checking of the command code, so

Page 21 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

if you use a bad name for an attribute, it will not show up as an error until
Simics runtime when you try to use the commands.

Figure 18. Simics Object Browser: Status Command

Page 22 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

THE DEVICE DRIVER


The next part of the puzzle is the device driver. This is a Linux kernel
module that talks directly to the hardware driver, and exposes a char
device interface to the software.

A good starting point to understand Linux device drivers is the book called
“Linux Device Drivers, 3rd edition”. It can be bought in paper form, or
downloaded from http://lwn.net/Kernel/LDD3/ . It is highly recommended
to have some such reference handy when working with the device driver.

The code is found at:


base/linux-kernel/linux-2.6.23/drivers/char/simple_example_driver/

It consists of several files:

ƒ simple.h is the common header


ƒ simple.c contains the initialization code
ƒ simple_hw.h/.c contains the hardware mappings and hardware-
interface of the driver, including a set of convenience functions.
ƒ simple_file_ops.h/.c contains the file operations facing the user-level
software.
ƒ README provides more details and suggestions for improvements to the
driver.

Building the driver


The driver is built by going to the base/linux-kernel/linux-2.6.23/ directory
and issuing “make” (after making some change to the driver). This will
result in a new simple_example_driver.ko loadable kernel object that can be
used on the target machine.

Page 23 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Figure 19. Building the device driver

An example of how to build is shown in Figure 19.

Verbose build
If you want to check on the detailed invocation of the cross-compiler on
the device driver code, you use the command “make V=1” instead. V=1 tells
the Linux kernel make system to be verbose and tell you all it does and the
complete command-line invocation of compilers.

Loading the driver onto the target


To load the driver onto the target, you need to first have a booted
MPC8641D target machine configured with the simple_device in place.
You get this from the “mpc8641d-hsi-course-booted.simics” script.

The script “hsi-course-load-driver.simics” can then be used to load the


driver on the machine. It automates several steps on the target machine:

ƒ Mounting host, copying the most recent driver in, and unmounting the
host.
ƒ Doing an insmod to make the kernel load the driver, and providing and
argument to insmod to tell the driver where to find the hardware.

Page 24 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

ƒ Creating the device node /dev/simd so that programs can access the
device, using mknod.

Linux uses device numbers to call the right driver for the right node in
/dev/. For this setup, we use the major number 240 and minor 100, since it
will only be used in this system, and thus it is fine to use one of the
numbers set aside for local use. There is no need to complicate things with
automatic assignment of dynamic device numbers at this point in time.

Using the device via the Linux file system


The way to use the device is via regular Linux file system calls. Our
device is used in the following way:

ƒ Do open() on /dev/simd to get a file handle to the device


ƒ Use write() to send data to the device
ƒ Use read() to get results back. Read will block until the results are
available, as indicated by the status.OC bit in the hardware.
ƒ Finally, close() the file.

The test program described below does exactly this.

Modifying the device driver


The device driver will need to be modified as the device hardware design
changes. It is suggested that new hardware registers are declared in the
header file simple_hw.h, and that all interaction with the hardware is kept
local to simple_hw.c. The file operations in simple_file_ops.c should call
functions in simple_hw.c, unless it turns out that performance requires some
code to be inlined in the file operation code.

The driver code is extensively commented to help you find your way
around.

The example code for the Linux Device Drivers book is a good source of
snippets of code to extend the driver.

Note that as noted in the README file, the device driver has plenty of room
for added functionality.

Page 25 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

THE TARGET PROGRAMS


The test programs intended to run on the target machine are found in the
Simics workspace, at targets/mpc8641-simple/target-code/. There are two
programs currently:

ƒ is a program that should be accelerated.


rule30_cellular_automaton
ƒ is a test program that uses the device driver and
simple_device_test
example simple device.

Building target programs


To build them, go to their respective directory and issue “make”. Figure 20
shows how a build looks. The programs are cross-compiled for the
MPC8641D target using the cross compiler provided.

Figure 20. Building a target program

The target programs are built to have an extension .elf, to make it easy to
see that they are not host programs (since they are cross-compiled).

Page 26 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

The file called Makefile.generic in the target-code/ directory contains the


generic rules for building target programs, and the Makefile files in each
program directory lists the files which are part of each program.

Running target programs on the target


To run a target program on the target, you need to have a booted target
machine. If you want to use the device and its device driver, you should
also make sure that these have been setup. You then use simicsfs to copy
the target software from you host to your target, and run it on the target.

Note that once a program has been copied into the target disk, it can be
rerun any number of times. There is no need to recopy it unless you have
change the code in some way.

The provided programs all use command-line parameters for configuration


and flexibility. The driver test program accepts the /dev/ node to use, and
the rule30 program the number of generations to run.

There are Simics scripts provided to automate the loading of programs:

ƒ hsi-course-load-rule30.simics loads the rule30 program into a booted


target and runs it.
ƒ hsi-course-load-test-program.simics loads the test program into a
machine that has configured the device driver.
ƒ hsi-course-booted-load-driver-and-test.simics does a complete test run
from a checkpoint, loading the driver, and the test program.

Note that you can run scripts like “hsi-course-load-rule30.simics” from the
Simics GUI using the command “Append from Script…” on the File menu,
after the machine has been booted or a checkpoint opened.

Modifying the target programs


The target programs are standard Unix command-line programs. The
cross-compiler and target file system contain the standard C library
functions, so there are no obvious limitations due to the nature of the
target.

Page 27 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

THE LINUX KERNEL


In most cases, students should not need to rebuild or change the Linux
kernel used in the course setup. However, all the source code is provided if
it would prove needed. It can also be quite instructive to actually do some
reconfiguration and recompilation of the kernel, just to see how it is done.

The present kernel configuration has been configured for use on the
particular simulation setup we have in place only, with certain device
drivers that generated warnings about accesses to non-existing memory
and similar deactivated.

All device drivers and features being used are configured as statically
loaded modules, i.e., part of the compiled kernel binary. This is typical for
how embedded systems are usually configured, simply because you know
the hardware you are running on and the applications it is supposed to run.
Desktop and server setups tend to use loadable modules far more.

Note that since we are using dynamic module loading for our device
driver, all the support for loading modules dynamically is configured to be
present.

Building the Kernel


To build the kernel, go to base/linux-kernel/linux-2.6.23/ and enter the
command “make”, just like when building the device driver.

To reconfigure the kernel, issue “make menuconfig”, and you should get the
interactive setup shown in Figure 21.

Page 28 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Figure 21. Make menuconfig for Linux kernel

To use the new kernel in the Simics simulation setup, you need to copy
two files to the Simics workspace file tree:

ƒ uImage, which is the U-Boot compressed image used in the actual


target system. This file is found in base/linux-kernel/linux-
2.6.23/arch/powerpc/boot/.
ƒ vmlinux, which is the ELF-format file for the kernel that is used to
debug the kernel (it contains symbols and is readable for debuggers
like Simics and gdb). This file is found on the top-level Linux build
directory, at base/linux-kernel/linux-2.6.23/

The two files need to be copied to base/simics-workspace/targets/mpc8641-


simple/images/ to be picked-up and used by the Simics scripts. Note that
any checkpoints created using an earlier kernel version should be
discarded and regenerated – these have already loaded the kernel into
memory, and will not change their kernel setup just because a file in the
host file system changed.

Page 29 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Enabling Debug Information in the Kernel


The Linux kernel per default does not generate debug line number
information, only symbols (this means that you can tell which function you
are in, but not where in that function).

To get more information for symbolic debug, you need to explicitly enable
debugging information in kernel setup. This is done under “Kernel Hacking”
in the setup system, as shown in Figure 22.

Figure 22. Kernel hacking: Enable debug support

Enabling “Kernel debugging” brings up a large set of new options, many


of which add instrumentation support and extra checks to the kernel
behavior. Figure 23 shows some of the debug options available for use to
help debug system behavior. In particular, enabling debug information to
be generated in the kernel build.

Page 30 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Figure 23. Kernel debugging options

Page 31 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Note that if you build the kernel with debug information and ask Simics to
load that debug information, the Simics process will get quite large due to
the need to represent the line-number information in Simics.

The kernel is a fairly large piece of software, and just the compiled debug
information is on the order of 35MB. Loading that into Simics will require
a few hundred MB of host memory to represent, so make sure that you
host has plenty of memory. In particular, running Simics inside a VmWare
virtual machine might make this operation swap like crazy. Therefore, it is
no recommended to use a full debug-information kernel unless absolutely
necessary. Note that the default build does have symbol information that
tells you which function you are in, which is often sufficient.

Page 32 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

HARDWARE-SOFTWARE INTERFACE DESIGN


There are some recurring patterns in hardware-software interface design,
some of which are already present in our simple example device.

Status and Control Registers


You always need one register to set basic controls for a device, and one
register to read out its status. Sometimes, one register is used for each
aspect, but quite commonly several flags or settings are combined into a
single register. This makes for some fiddling when getting out individual
bits in a driver, but also makes it poss ible to set many settings and get
many status details with a single hardware access. This has advantages for
convenience and consistency of the state. In DML, such register fields is
very simple to program, as shown in Figure 24.

Figure 24. Register fields for control register of simple device in DML
register control @ 0x04 "Device control register" {
field OP [1:0] "Operation select" {
// read-write semantics
method write(value) {
$this = value;
inline $reset();
log "info", 2 : "Operation selected: %d", $this;
}
}
field IE [2] "Interrupt enable" {
method write(value) {
$this = value;
if(value==1) {
log "info", 2 : "Enabling interrupts";
} else {
// Lower our flag about having raised an IRQ
// and lower IRQ if it was raised
log "info", 2 : "Disabling interrupts";
inline $clear_interrupt_if_raised();
}
}
}
}

Writes to the control register will usually have side-effects, while reading
should not so that software can check the device settings without changing
anything.

A status register should be readable without side-effects. An older


hardware pattern that used to be quite common was “read clears”, so that
once you had read a register all information flags and raised interrupts and
similar was cleared as a side-effect of just reading it. This is a bit brittle in
a complex software stack, and the recommended way to clear states and
flag is to use a write. A common idiom is “write 1 clears”, which means

Page 33 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

that a flag is cleared if a bit value of one is written to it. This makes it easy
to clear a range of flags with a single write, and also to leave certain flags
alone by just writing them as zero bits.

Polling
The simplest way to drive most hardware is to use polling, where the
software keeps reading some status register bit to tell if the hardware has
completed its operation. This means that you should always have
“operation complete” indicators in your hardware status registers.

The input registers are designed in such a way that there is no need to have
a flag for “input accepted”. Essentially, the hardware device will not
complete the write operation from the processor until it has put the data it
received in the right place internally.

Interrupts
If a device can raise interrupts, it needs a few facilities in place:

ƒ A way to tell the device to generate interrupts, usually a single


“interrupt enable” bit in a control register. By default, a device should
not raise interrupts until told to.
ƒ A way to see if an interrupt has been raised, and why. This is one bit
or more in a status register.
ƒ A way to lower the interrupt once the software has serviced it.
Usually, by writing to the status register to clear the interrupt flag.
ƒ Some way to forcibly reset the interrupt state of the device, to force a
clearing of raised interrupts and all interrupt status flags. This is
needed so that a device driver can force the device into a known-good
state when initializing it, for example.

The reason you want to have explicit status bits for interrupt status is that
several devices could share a single interrupt line to the processor, and the
device drivers would then need to look at the device status registers and
tell which device or devices raised the interrupt.

In our simple device example, the interrupt status bit is the same as the
general operation complete bit.

Starting operations
Starting a hardware operation can either be explicit or implicit.

Our simple device has an implicit design, where writing to the single input
registers begins an operation, and the point of operation complete is

Page 34 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

pushed out each time. This is a bit simplistic, since it basically assumes
that the hardware has an infinitely long pipeline that can accept any
amount of input.

A more common pattern is an explicit design where the hardware


essentially has a “start” button. Here, you write input to a large number of
input registers to setup the desired operation, and then a final write to a
control register begins the operation. After this, the software goes off to
wait for an interrupt or polls the operation complete flag.

To get an example of such a design, the easiest is to copy some of the


example code provided with Simics. At a Linux command-line prompt at
the Simics workspace top level, issue the command:
bin/workspace-setup --copy-device=sample-dma-device

This will copy the device called “sample-dma-device” into base/simics-


workspace/modules/sample-dma-device/. In this code, you have several
DMA settings registers that you setup before starting a transfer by writing
both the “EN” and “SWT” bits in the control register shown in Figure 25.

Figure 25. Register fields for control of sample-dma-device


register DMA_control size 4 @ 0x00 "DMA control register" {
field EN [31] "Enable DMA";
field SWT [30] "Software Transfer Trigger";
field ECI [29] "Enable Completion Interrupt";
field TS [15:0] "Transfer size (words)";
method after_write(memop) {
inline $do_dma_transfer();
}
}

This code requires some additional explanation. Note how it does an


“after_write()” operation rather than the straight write() used previously.
The reason for this is that the effect of a write to the control register
depends on the value of several bits. The DML write() methods for bits in
a register are called in order from low to high bits to generate the new
value of the register, which means that a write() method for a particular
field cannot assume that the effect of writing other fields has taken place
when it is being called. The solution to this is to have an after_write()
method that is called once the entire register has been updated.

More reading
The number of sources on this topic is fairly limited, but here are a few
links:

Page 35 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

• Gary Stringham and associates has a newsletter addressing various


hardware-software integration issues, which can be found at
http://www.garystringham.com/newsletter.shtml

Page 36 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

DML PROGRAMMING TIPS


This chapter will address some additional techniques for programming in
DML.

Device-internal registers
DML supports the generation of registers that are internal to a device and
that have software-accessible interface. This is useful to model internal
state registers, for example, in a way that is consistent with other registers.
The syntax is simple: apply the template “unmapped” to the register, as
shown in Figure 26. Such registers are checkpointed like other registers,
and are visible in the Simics register viewer. It is the best way to code
internal registers in a device.

Figure 26. Unmapped registers in DML


bank regs {
register op_state size 4 is (unmapped);
register to_state_1 size 4 @ 0x00 {
method write(value) {
// do work...
$op_state = 1;
// ...
}
}
method state_dependent_op() {
if($op_state == 1) {
...
}
}
}

Note that if the register represents a configuration parameter to the device,


like the IRQ level in our example device, it is most appropriate to
represent it as an attribute.

Large input buffers


If your device interface design needs a larger input buffer that can accept a
large block of data, there are two ways to code this in DML.

The simplest solution is shown in Figure 27. You essentially allocate a set
of registers in an array of registers, and have the software write this. The
device model can then access the written data using array notation. Note
that this solution does not really create a memory buffer that can be
accessed using accesses of any size, but really just an array of registers. To
read out the contents, you have to work on units the size of the registers.

Page 37 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Figure 27. An input buffer represented as an array of registers


bank regs {
// Give this parameter for an entire bank to allow all registers
// to be accessed as bytes and subwords as well as in full
parameter partial=true;
...
// Put down 200 registers as offset 0x100, 0x104, ..., 0x41c
// They have to be read as 32-bit values in the device model
// Note the explicit multiplication of the index by four to get
// a correct offset.
register buf[200] size 4 @ 0x100 + $i*4;
...
}
...
method do_work() {
...
local int i;
local uint32 s;
for(i=0;i<200;i++) {
s += $reg.inbuf[i];
}
...

// Alternate variant, copy data into a local array for further


// processing, for example in an external C function
local uint32 b[200];
for(i=0;i<200;i++) {
b[i] += $reg.inbuf[i];
}
...
}

Note that you can make 32-bit registers byte-writable from software by
giving the parameter “partial=true” to the bank, as shown at the top in
Figure 27. This generates a bit more code for your device model, and
usually real hardware does assume aligned full-size writes to registers, so
it is off by default.

A more complicated solution is to use the Simics image system to


represent this more as general memory is represented. This is described in
the Simics manual “Modeling Your System”, section 5.2.4, “Saving Data”.

Internal temporary data buffer


When you need to represent some data global to a device, but that data
does not need to be checkpointed and is really only used for optimizations
or convenience of access, you can use the data keyword in DML.

Items declared as data are not checkpointed, so their use should really be
restricted to temporary information that is created and used during a single
execution step (implementing a memory operation or event callback), or to
data that is trivial to reconstruct from other information in the device.

Page 38 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

For example, for ease of computation, you might want to expand a terse
bit-based input register into an array of bytes in your device model to be
used from several separate functions during a single simulation step. This
is just an internal optimization, and the true state of the device is still
represented by the value of the register. An outline code is shown in Figure
28, note that both the write and set methods have to be overridden for this
to work correctly. This example is also checkpoint-safe.

Figure 28. Expanding input data to an internal buffer


data uint8 expanded_buffer[8];

bank e {
register input size 1 @ 0x00 {
method write(value) {
// Expand data to the buffer
$this = value;
inline $do_expand();
}
method set(value) {
// expand data on attribute set, to support checkpoint
$this = value;
inline $do_expand();
}
// get and read do not need changing, they are just reporting
// the byte value in the register
}

method do_expand() {
// iterate across bits in $input
// set the bytes in expanded_buffer
// ... implementation abbreviated ...
}
}

Note that if you can, you should try to use a local variable inside a single
method or function instead, as shown above in the second part of Figure
27. This avoids any checkpointing issues and makes it clear that data is
temporary.

Including C code in a DML device


DML does support putting in arbitrary C code in a device. This is
documented in the Simics documentation, but the short version is that you
have optional header and footer sections in the DML source file that inserts
arbitrary C code before and after the code generated from the DML code.
Typically, header is used to include the C header files needed for the code
in the C code to work, and footer contains the actual implementation code.
The best way to communicate data from the DML code to the C code is to
use arguments to the C functions, not to try to peek into the device data
structure generated by DML (even if that can be done and is well-defined
in how it works).

Page 39 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Modeling configuration pins


Sometimes a chip or a function block inside a chip has a set of pins that are
wired to 1 or 0 (pull-up or pull-down) by the surrounding system. This
could be, for example, jumper switches on a board, or simply constant
pull-up/down connections inside a chip. In Simics, such pins are best
modeled as attributes, so that they can be set in the configuration (and
changed from the command-line).

The code in Figure 29 implements three such configuration pins, using a


couple of DML templates. Note the use of configuration=pseudo to make the
register not be checkpointed (as its value is derived from the existing
attributes which are checkpointed), and allocate=false to remove the need
for storing any data for the register in the device data structure, as that is
already stored in the attributes. This code works with the device viewer
and the software view.

Page 40 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Figure 29. Modeling configuration pins


// Template for the attributes
template pin_attribute {
// "b" means “bool” and restricts setting the attribute to true/false
parameter type = "b";
// The data is stored in integer form due to a pecularity
// of the Simics API that returns integers valued 0 or 1
// for boolean attributes.
data int value;
method get() -> (result) {
result = SIM_make_attr_boolean($value);
}
method set(attr_value) {
$value = SIM_attr_boolean(attr_value);
}
}

// The attributes get the good easy to understand names,


// as they are accessed in the configuration.
// dev0->pin_1 etc. is the way to access them
attribute pin_1 is (pin_attribute);
attribute pin_2 is (pin_attribute);
attribute pin_3 is (pin_attribute);

template wired_pin_field {
// Set pin_attribute to tell us which attribute to read
parameter pin_attribute default undefined;
// Make this not stored in the device data structure
parameter allocate = false;
method write(value) {
log "spec_violation" : "Writing hard-wired bit %s", $qname;
}
method read() -> (result) {
result = $pin_attribute.value;
}
// read current value for checkpointing and device viewer
method get -> (v) {
inline $read -> (v);
}
method set(v) {
// Should not get called, but ignore values written
}
}

bank wired_config {
register values size 4 @ 0x00 {
// To not checkpoint this value, as it is redundant
parameter configuration = "pseudo";
// Then the fields
field p1 [0] is (wired_pin_field) {
parameter pin_attribute = $pin_1;
}
field p2 [1] is (wired_pin_field) {
parameter pin_attribute = $pin_2;
}
field p3 [2] is (wired_pin_field) {
parameter pin_attribute = $pin_3;
}
}
}

More device example in Simics


Note that there are several more example devices available in the Simics
installation, just do “bin/workspace-setup --copy-device=badname” to get a list

Page 41 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

of all available example code modules (giving the name of a non-existing


module to the script will make it list all available modules).

DEBUGGING TIPS
A virtual platform offers a very good base for debugging the hardware-
software integration as it is far easier to see what is going on compared to
a physical hardware setup.

This section will give you broad ideas for how Simics can be used in
debugging problems. For the details, please see the Simics documentation,
in particular:

ƒ Modeling your System in Simics.


ƒ Advanced Features of Simics.
ƒ Using Simics for Software Development.

Device Activity
To peek at the activity towards any device, you have several tools at your
disposal, at the Simics command-line. We assume the object for our
simple device in Simics is called “sd0”.

ƒ break-io sd0: breaks execution as soon as anything accesses the


device.
ƒ trace-io sd0: prints all accesses but does not stop
ƒ sd0.log-level 2|3|4: increase the level of logging going on
ƒ mpic.log-level 2|3|4: do more logging in the interrupt controller
ƒ trace-exception: trace exceptions hitting the processors in the system
ƒ break-exception: break execution with an exception hits a processor
ƒ output-radix 16 2: set default output to hexadecimal format,
sometimes helpful to better parse bit fields and byte orders
ƒ si: step a single instructions, quite useful to see the effect of raising an
interrupt or doing a write
ƒ peq: print all pending events in the Simics event queue, useful for
debugging event posting for delayed events. Often used with –all flag
to see all.

In the target Linux, you can do some checking of what the kernel has
logged in terms of events:

ƒ cat /proc/interrupts: lists all interrupts that the kernel has handled
ƒ cat /proc/devices: lists all active devices

Page 42 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

ƒ cat /proc/modules: lists all dynamically loaded modules, which should


only be our simple device driver, as all other drivers are statically
linked to the kernel.
ƒ dmesg: print the contents of the the printk kernel message buffer

Device Logging
It is a very good idea to pepper your device code with log statements as
you initially figure out how to do things. They can be removed later, or left
in at a high level of logging (they do not hurt performance if not
activated). See Modeling Your System in Simics, Section 3.7.

The standard log levels used in Virtutech devices are the following:

1. Important: Error messages and very important messages, for example


“Ethernet controller receive functionality not implemented”
2. Informative: High-level information like mode changes and events, for
example “Ethernet port status changed to link-up”
3. Debugging: Medium level of information. More detailed than level 2.
For example, “Ethernet controller saved received frame at
0x1000BEA0”
4. Detailed debugging: Detailed messages about what is happening in the
device, for example “Ethernet controller received an ARP frame with
correct CRC and moved it queue 0x01 to be handled in 100 cycles”

Device Attributes and State


All registers and attributes in a DML source file automatically have Simics
attributes generated for them. This provides back-door access to the state
of a device, for both reading and changing it. To read an attribute of a
Simics object, you can either:

ƒ Use the command sd0->ATTRIBUTENAME on the Simics command-line.


Note that all registers in the bank regs have attributes generated with
names starting with “regs_”. There is no hierarchical namespace. See
the bottom of Figure 31 for an example attribute access.
ƒ Define sd0.info and status commands, as discussed above.
ƒ Use the Simics GUI Device Registers window shown in Figure 17.
However, that only shows the registers, not other attributes.
ƒ Use the Simics GUI Object Browser to look at all the attributes of the
device, as shown in Figure 30.

Page 43 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Figure 30. Simics Object Browser

Writing a Device Memory Map from the Simics CLI


You can read and write the memory-mapped registers of a device directly
from the Simics command-line, to see that memory writes have the
intended effect (and often that appropriate log messages are seen). To do
this, you use the command write or read on a memory space in Simics. In
our setup, the relevant memory spaces are ccsr_space, where the device is
mapped at 0xf0000 (in the default configuration) and phys_mem, where the
device is mapped at 0xf80f0000, as seen from the processor.

Figure 31 shows an example session using read and write. Note that the
reads and writes seem to come from cpu0 for the device, and by design
there is no way to differentiate them from regular processor reads and
writes. If you want to see or change values without looking like a
processor, use the attribute mechanism (or the device viewer shown in
Figure 17).

The write command works like this: MEMORYSPACE.write ADDRESS VALUE


[SIZE], where SIZE is optional and defaults to 4 bytes. Note that the ADDRESS
is local in the memory space. MEMORYSPACE.read ADDRESS [SIZE] reads a value
from memory, with the same argument types as write. You can also force
the endianness of the access to be little-endian or big-endian, but that is not

Page 44 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

an issue in the completely big-endian Power Architecture system that we


are working with here.

Note that write and read have side-effects, and that is what you want for
device testing. There are also MEMORYSPACE.get and set commands that
generate “inquiry” accesses which do not have side-effects. These are not
that useful for device model testing.

Figure 31. Device read and write from the command-line

simics> output-radix 16 2
simics> ccsr_space.read 0xf0000
[sd0 trace-io] Read from cpu0: 0x0f_00_00 4 0xab_cd_00_01 (BE)
0xab_cd_00_01
simics> ccsr_space.write 0xf0000 0xdeadbeef
[sd0 spec-viol] Write to read-only field regs.version.V_MINOR (value written = 0xef, contents = 0x1).
[sd0 spec-viol] Write to read-only field regs.version.V_MAJOR (value written = 0xbe, contents = 0x0).
[sd0 spec-viol] Write to read-only field regs.version.COOKIE (value written = 0xdead, contents = 0xabcd).
[sd0 trace-io] Write from cpu0: 0x0f_00_00 4 0xde_ad_be_ef (BE)
simics> phys_mem.write 0xf80f_0000 0xdeadbeef
[sd0 spec-viol] Write to read-only field regs.version.V_MINOR (value written = 0xef, contents = 0x1).
[sd0 spec-viol] Write to read-only field regs.version.V_MAJOR (value written = 0xbe, contents = 0x0).
[sd0 spec-viol] Write to read-only field regs.version.COOKIE (value written = 0xdead, contents = 0xabcd).
[sd0 trace-io] Write from cpu0: 0x0f_00_00 4 0xde_ad_be_ef (BE)
simics> simics> sd0->regs_version
0xab_cd_00_01

If you want

Driver Logging
Using printk() in your driver code offers a way to have it tell you what it is
doing. Note that it is not good to put this on the common calls like write()
as the target console will mix the printk() and application-level printouts
on the same line. When the driver detects errors, however, printk() can
definitely be a very useful way to signal driver state.

Use the kernel various defined KERN_x printk levels. To remove debug code
when not used, use local DEBUG_SOMETHING defines in the device driver. There
is currently a few of these defined in simple.h and used in the various .c
files.

Linux Kernel Debug Features


The linux kernel used can be rebuilt to include more debug features and
run-time checks. Currently, the default setup is intended for run-time use,
and does not enable these hooks. See “Enabling Debug Information in the
Kernel” above for more information.

Page 45 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

Application Program Logging


Output in the application program is natural to do to see the flow of
execution, but it should not be part of tight inner loops that you want to
benchmark or accelerate. The core problem here is that doing serial output
is very expensive in terms of execution time, and will likely skew or
completely swamp performance results.

Simics Debugger
Simics has a built-in debugger that can handle both kernel-level and user-
level code. We will get back with a description on how to use these.

PERFORMANCE MEASUREMENT
More to come.

Page 46 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

SUMMARY
This application note has presented a complete teaching setup based on
Virtutech Simics, the Freescale MPC8641D virtual platform, and the
Linux operating system. This setup can be used to teach a variety of topics
related to how hardware and software interact. It provides students and
teachers a complete software stack for a realistic target, with the flexibility
to change any part, including the hardware.

CONTACT INFORMATION
North and South America Europe, Middle-East, Africa

sales_americas@virtutech.com sales_emea@virtutech.com

Asia-Pacific Japan

sales_apac@virtutech.com sales_japan@virtutech.com

http://www.virtutech.com

© Copyright 2008 Virtutech, Inc. All Rights Reserved.


TRADEMARKS. Virtutech, Simics, Hindsight, and the logos thereof, are trademarks or registered trademarks of Virtutech, Inc.
and/or its subsidiaries, in the United States and/or other countries.

Page 47 / http://www.virtutech.com © 2008 Virtutech


T EACHING H ARDWARE -S OFTWARE I NTEGRATION WITH S IMICS

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.
Virtutech, Inc., 2001 Gateway Place, Suite 201E, San Jose, CA 95110, USA

Page 48 / http://www.virtutech.com © 2008 Virtutech

You might also like