Running Simulated Systems

TEMU models and functionality is primarily built around the TEMU Object System.

Runnable items are no different, and they are implemented following a common type called a Time Source.

A time source is responsible for tracking its own time, clock rate, an event queue and a parent time sources.

It is possible to run any time source in TEMU, this includes:

  • Clocks

  • Processors

  • Machines

  • Schedulers

The scheduler was introduced in TEMU 4 to expose a parallel scheduler. The machine in turn is the legacy single threaded scheduler. A processor and clock are bottom level time sources.

To run machines, processors or clocks the user invokes the global run-command, passing the time source as the obj-parameter.

However for the scheduler, the corresponding command method in the scheduler should be invoked.

Stepping and Running

TEMU distinguishes between running and stepping a system.

When running a system, the whole system runs freely for some time. At the end of the run (ignoring early stops such as breakpoints), the local time for each processor should be roughly the same.

When stepping a system, we are instead controlling the exact number of executed instructions for one of the processors. When the processor in question exceeds it’s quanta, other processors may run.

Processors and Clocks

Processor and clocks are the lowest level in the scheduler hierarchy. Processors and clocks can be run using the CpuIface or the ClockIface.

Command Line

run obj=cpu0 time=1.0

# Step a processor for two instructions
step obj=cpu0 steps=2

API

// Run processor for 10000 cycles
cpuIfaceRef.Iface->run(cpuIfaceRef.Obj, 10000);

// Run processor for 10000 steps
cpuIfaceRef.Iface->step(cpuIfaceRef.Obj, 10000);

Machine Model

The Machine model is deprecated as of TEMU 4.0; in favour of the Scheduler.

The Machine-model was the traditional way of running multi-core processors in TEMU 2 and 3.

The machine model is an object that collects several processors together, enabling them to be run as one unit.

The model runs processors in a round-robin schedule. Each processor is executed for a quanta, before running the next processor. The length which is configurable on the machine in simulated nanoseconds.

As the machine is using nanoseconds, it cannot be used for processors running faster than 1 GHz.

Command Line

// Step processor number 1 in the machine for 10 steps
step obj=machine0 cpuidx=1 steps=10

API

// Run the machine for 10000 nanoseconds
machineIfaceRef.Iface->run(machineIfaceRef.Obj, 10000);

Scheduler

The scheduler model is currently not controllable by the GDB Server. To use the TEMU GDB Server, the Machine model must be used instead.

The TEMU Scheduler is a globally available object. The last created Scheduler-instance is automatically registered as the current scheduler.

When running the scheduler, the processors registered in it will run in parallel if so configured. However, when stepping the scheduler, the scheduler falls back to serial round-robin scheduling in order to remain deterministic.

Command Line

Creating a Scheduler
Scheduler.new name=sched
sched.set-frequency frequency=cpu0.freq
sched.set-quanta quanta=20000

# Configure scheduler to run in 2 threads,
# binding cpu0 and cpu2 to thread 0,
# and cpu1 and cpu3 to thread 1.
sched.set-threads threads=2
sched.bind-to-group group=0 cpu=cpu0
sched.bind-to-group group=1 cpu=cpu1
sched.bind-to-group group=0 cpu=cpu2
sched.bind-to-group group=1 cpu=cpu3

# In single threaded mode, the processor will ignore flush
# instructions, but in multi-threaded mode we need to
# treat this as a proper instruction cache synchronization.
cpu0.config.exitOnSync = 1
cpu1.config.exitOnSync = 1
cpu2.config.exitOnSync = 1
cpu3.config.exitOnSync = 1

# The memory space must collect invalid page lists in multi-threaded mode,
# in single threaded mode the pages can be purged when written directly.
mem0.config.processorHasSync = 1
Running and Stepping the Scheduler
# Run the simulator for 10 seconds
sched.run secs=10.0

# Step processor 2 for 10 steps
sched.step cpu=cpu2 steps=10

API

Running an Already Created Scheduler in C
// Run the scheduler for a 2 seconds
temu_runSecs(2.0);

// Step the cpu (which is a temu_TimeSource pointer) for 10 steps.
temu_step(cpu, 10);

// Stop the currently running scheduler and wait until it is stopped.
temu_stop();

// Stop the currently running scheduler, but return immediately.
// The function is async-safe and can be run in signal handlers.
temu_asyncStop();