memory-mapped IO

A while back, we implemented addressable storage. We’re now going to crack this open and make it much more versatile.

a model of memory

Let’s look at a single block of memory.

We can think of this as its own device. This device implements two functions:

  • Read — we can read data off it
  • Write (for writeable memory) — we can write data to it

Our addressable storage contains a list of these devices, each with its own address. We use that address to decide what device we’re going to visit to read/write our data.

But here’s something interesting: we can put different types of devices at different addresses.

For instance, we previously designed an (impractical) scrolling display. What happens if we connect the display’s input to an arbitrary memory address — let’s say #17?

Whenever our computer executes STORE #17, it sends a bitstream to that address. But instead of storing the data in memory, the data will be fed directly into the screen! Effectively, STORE #17 becomes our way of saying PRINT TO SCREEN.

Similarly with input, we could connect some kind of keyboard device to (e.g.) address #33. Then when we say READ #33, we’d be receiving the user’s input; so READ #33 becomes code for READ KEYBOARD INPUT.

This is called memory-mapped IO (“IO” is “Input/Output”). The other approach, where we use dedicated INPUT and OUTPUT instructions, is called port-mapped IO.

definition

memory-mapped IO uses memory addresses to talk to input/output devices.
port-mapped IO uses dedicated instructions to talk to input/output devices.

applications

This approach simplifies our instruction set. It means we don’t need a dedicated INPUT or OUTPUT instruction.

It also gives us more flexibility. Suppose we later want to add some other input/output device — maybe a second screen. We can just plug it into another memory address. We now have a PRINT TO SCREEN 2 instruction for free.

disadvantages

Memory mapping seems like a great approach, right? We might expect all computers to use it. However, it turns out that pure memory-mapped IO comes with a bunch of headaches that reduce performance.

For example, computers like to cache memory. This means copying a piece of slow-to-read memory into a much faster temporary location. But if the memory at that address isn’t memory at all (because it’s a physical device), how can we cache it? Therefore we have to disable caching for that region of memory, or come up with special caching techniques to make sure the device stays in sync with the cache.

Therefore, most computers use a hybrid approach — port mapping for some things, memory mapping for others.

extending this

With memory mapping, we can remove the need for instructions like INPUT/OUTPUT. Next, we’ll see how we can remove the need for instructions at all.

continue