System Organization

One may consider the fixed low-level SID API as a socket, or a standardized connector between simulated components. Think of SID components as integrated circuits that plug into these sockets and configuration files as the circuit wiring that connects the sockets to each other. To simulate an entire board, many different components will be needed, and their connections need to be set up just right for SID to work.

While the configuration process is described in detail in a later section(see the chapter called Working with the SID Configuration File>), there are common patterns of configuration in typical SID simulation runs. These sketches outline some of these patterns.

Main Loop, Schedulers

In a running SID simulation, activity occurs in a single thread. It passes from a central top-level loop down through components and back, by calling SID API functions. More specifically, the top level loop signals each iteration on a designated pin. Each component that connects a pin to it will be invoked to do some work. This work may include internal calculations, changing attributes, or could involve making pin- or bus-related function calls to other components. Then those components do some work, and so on. When these work units are complete, control returns to the top level loop, which then goes around for another iteration.

There also exist control pins that cause and indicate the initialization and shutdown of a simulation run. This allows components to monitor or effect changes to the top-level looping. For example, simulated CPU executes the target program's exit() system call, the component that interprets system calls will signal this event on a pin. If that pin is connected to the main loop's shutdown control pin, the simulation will shortly end.

Many components may wish to regulate the rate at which control is passed to them. They may have nothing to do at times (like an idle DMA controller). Some may wish to act at independent frequencies (like a CPU and a timer). Several special function components exist to keep simulation time and dispatch events to other components only at intervals of interest: these are the scheduler (sid-sched) components.

There is usually one host-time scheduler and one target-time scheduler in a simulation run. Both are connected to the top level activity pin. Components that interface between the host and the simulated target often use the host-time scheduler (sid-sched-host), so they get activity signals at rates related to passing wall-clock time. Components that model the hardware of the target system are generally connected to the target-time scheduler (sid-sched-sim), so target activity may be suspended/resumed en masse by a debugger.

Peripherals, Memory Mapping

A typical SID configuration one or more CPU models, some banks of memory, and several peripherals. When the CPU executes a load or store instruction, the correct SID component must be addressed to carry out the memory access. This decoding operation is performed by an intermediary: a mapper component that is configured with the target board's memory map.

The CPU component is usually connected to the slave side of the mapper, and the master side of the mapper is connected to multiple slave peripheral components. Other bus master components may also connect to the mapper similarly. When a bus master makes a read or write call, the interposed mapper component decodes the address, and passes the read or write call to the specific component being addressed.

In effect, the mapper transforms the CPU's view of the address space to peripheral-centric views. This way, neither the CPU nor the peripheral is aware of the target board's memory map: this knowledge is encapsulated in a mapper.

There may be several mapper components in a simulation run. This is appropriate if there are separate instruction and data address spaces for a Harvard architecture CPU, or if address spaces are nested, or partly shared between multiple masters.

CPU, Monitor Emulation, Debugger Interface