## 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.

### Devices

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. Provided for compatibility with old configurations; ordinarily the size of the disk image is used.
`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
|

### Timing

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:

- System/161 does not implement a cache simulator. All accesses are assumed to be satisfiable in one cycle from main memory. This is not completely crazy for a 25MHz cycle time; however, as cache effects are very important for performance today, it is displeasing. Future releases of System/161 may include more cache modeling.
- All instructions execute in one cycle. This is the intent of the MIPS architecture for most ordinary integer instructions; however, it should not be true for e.g. multiplies and divides.
- The disk timing model is weird and broken. Sometime it should be replaced with either a real one or at least a better one.
- The serial console was originally supposed to be 9600 bps; then it got cranked up to 19200 bps, and then a substantial fudge factor got inserted to make it go faster. At one time on one (old and slow) machine this made the output scroll at a speed comparable to a real 19200 bps connection. It hasn't been retuned since. This doesn't matter that much, but it's not actually the right speed for a serial console.

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.