System/161 Virtual Hardware

System/161 is a machine simulator. The virtual machine it simulates is a server-class computer, with a serial console, multiple CPUS, multiple disks, and one or more network interfaces. The formal processor clock speed is 25 MHz, the speed of a high-end server circa about 1990. This speed is a tradeoff between genuine processor speeds and the speed the simulator code can manage in real time, which is markedly lower.

The virtual machine is constructed in as simple a fashion as is reasonably possible while still maintaining most of the feel of real hardware. (The part of dealing with real hardware you miss out on is the part where the interfaces are screwy and the devices don't work half the time.)

The machine has 32 slots in a passive backplane bus called LAMEbus. One slot contains the system board with the LAMEbus bus controller. This board may contain up to 32 CPUs, each of which may potentially contain multiple cores. Each additional slot may be configured with any of several hardware devices. This configuration is established using a config file, named by default sys161.conf. Future versions of System/161 may provide a user interface for device configuration and/or allow devices to be inserted and removed on the fly ("hotplugged"), but this is not currently supported.

Programming information for LAMEbus

The system board contains up to 32 simulated 32-bit MIPS microprocessors. The MIPS is the simplest "real" 32-bit processor for which development tools are readily available; furthermore, the MIPS architecture is already widely used for teaching in various contexts. This makes it a natural choice.

Programming information for the System/161 MIPS processor

Config File Syntax

By default the config file is named sys161.conf and read from the current directory. An alternate file can be used by specifying the -c option. The syntax is line-oriented, with # comments. Each line specifies the contents of a slot, which may be between 0 and 31, and includes optional configuration arguments for the device to be inserted. The format of a configuration line is as follows:

slot-number device-name [args...]
The system board (bus controller) must always be placed in slot 31.


The devices available, and the arguments they support, are:
busctl Alias for oldmainboard.
disk Basic disk device
  rpm=cycles Specify rotation speed. Must be multiple of 60. Default is 3600.
sectors=sectors Specify number of 512-byte sectors on disk. Required.
file=filename Filename to use for disk storage. Required.
paranoid If set, call fsync() on every disk write to hopefully ensure data is not lost if the host system crashes. Slow and not recommended for normal operation.
nodoom If set, writes to this disk do not invoke the doom counter. Useful for swap disks.
Programming information
emufs Emulator pass-through filesystem
  dir=directory Directory to use as root of emufs filesystem. Default is System/161's current directory. The implementation translates symbolic links found in the host filesystem to regular files or directories, and no attempt is made to prevent accesses from escaping outside the named subtree. This allows the emufs tree to be populated with symbolic links that point elsewhere.
Programming information
mainboard Multiprocessor system board and LAMEbus bus controller
  cpus=num Specify number of CPUs, up to 32. Default is 1.
cores=bytes Specify number of cores per CPU, currently limited to 1. Default is 1.
ramsize=bytes Specify size of physical RAM, up to 16 MB. Must be multiple of CPU page size, usually 4K. Required.
Programming information
nic Network interface
  hwaddr=addr Set the hardware address for this network card. The hardware address is a 16-bit integer. 0 and 65535 (0xffff) are reserved for special purposes. Required.
hub=path Set the path to the socket for the network hub, hub161. The default is .sockets/hub.
Programming information
oldmainboard Old (uniprocessor only) system board and LAMEbus bus controller
  ramsize=bytes Specify size of physical RAM, up to 16 MB. Must be multiple of CPU page size, usually 4K. Required.
Note: this device is backwards-compatible with the System/161 1.x "busctl" device and should be able to run all old kernels.
Programming information
random Random number generator
  seed=number Set seed for pseudo-random number generator. Default is 0.
autoseed Set seed for pseudo-random number generator based on the system clock.
  Note: if you have multiple random devices, they all share the same randomizer state.
Programming information
screen Full-screen text console
  (no arguments)
Note: not implemented yet.
Programming information
serial Serial console
  (no arguments)
Programming information
timer Basic timer device
  (no arguments)
Programming information
trace System/161 trace controller
  (no arguments)
Programming information


System/161 maintains timings internally at a granularity of a single clock cycle; thus it can be used for very accurate profiling, to the extent that its execution time model is realistic.

The timings in System/161 have the following known limitations:

There is also the issue that System/161 cannot actually execute 25 million instructions a second, even on a fast machine. Therefore, on CPU-intensive tasks, it falls behind. In order to maintain the illusion that it continues to run at 25MHz, it distinguishes virtual time (within the simulation) from wall time (outside the simulation). All internal timings are calculated in virtual time.

Wall time is of interest, however, because the interactive behavior of the system occurs in wall time. For this reason, System/161 attempts to sync itself to wall time. For I/O-intensive tasks its interactive behavior is time-correct; for CPU-intensive tasks it is very slow. In the transition from one to the other some odd artifacts can occur; these can be made odder yet by scheduling interactions with the host OS if running on a busy system. These are most noticeable on the system console, but can also occur if one is using the virtual network.

For this reason, it's important to be cautious about evaluating software performance by eyeball; appearances can be quite misleading. Use the internal timers. If there's something you need to do that the internal timers can't support, please file a bug report.

Currently, when multiple CPUs are configured, they execute in lockstep in a single host-level thread, and the timing model is unchanged. It is likely in the future that it will become possible to run each virtual CPU on its own host-level thread; this will add major complications to the timing model, the full ramifications of which are not yet completely clear.