Memory Map
Recently I’ve been working on a revamped bootloader, turning it into a menu of cool built-in demos as well as its original purpose of downloading new programs from a remote PC. That’s led to some interesting tidbits, such as making the bootloader able to bootload itself. However, the biggest change to fall out of all this is a new memory map for BMOW.
You might be thinking that now is a strange time to consider rewriting the memory map, when the hardware is done and the machine is essentially finished, and you’d be right. Fortunately all of the relevant address decoding logic is contained in a single programmable GAL, and the memory and devices are connected to the address bus in a way that allows them to be located more-or-less anywhere in the address space, subject to some alignment requirements. The bulk of the work would be updating all the software I’ve written to work with a new memory mapping.
But why would I even consider a change like this? In the beginning, BMOW was conceived with a 16-bit address space, allowing for 64K of addressable memory:
Range | Size | Contents |
---|---|---|
$0000 – $3EFF | 15.75K | ROM |
$3F00 – $3FFF | 256 bytes | memory-mapped devices |
$4000 – $FFFF | 48K | RAM |
Pretty simple. But at the last minute before I began hardware construction, I decided to expand the address space to 24 bits, allowing for 16MB of addressable memory. I added a third byte to the address bus called the bank byte, along with the existing low and high bytes. The instruction set was left mostly unchanged, however, so most instructions use 16-bit addresses, and implicitly reference the current bank. Thus the address space was divided into 256 banks of 64K each, and program references to different banks are fairly awkward (think x86 segment registers, etc). I left the first 64K bank mapped as it was originally planned, but added more RAM and eventually video RAM elsewhere in the address space. As a result, the current BMOW memory map looks like this:
Range | Size | Contents |
---|---|---|
$000000 – $003EFF | 15.75K | ROM |
$003F00 – $003FFF | 256 bytes | memory-mapped devices |
$004000 – $07FFFF | 496K | RAM |
$080000 – $1FFFFF | unused | |
$200000 – $207FFF | 32K | Video RAM |
$208000 – $FFFFFF | unused |
A little odd, but it works. The problem I’m running into now with this memory mapping is that there’s only 16K of ROM. That’s not much space to fit a whole collection of cool built-in demos. Physically the ROM is actually 128K, so more space exists, it’s just not mapped anywhere into the address space. This is what ultimately motivated the change to the memory map that I’m contemplating now. I assembled a set of requirements and goals for the new memory map:
- $000000 must be ROM, because that’s where the CPU begins after a cold boot.
- The interrupt vector must be somewhere in the first three banks ($000000 – $02FFFF) or last two banks ($FE0000 – $FFFFFF), due to limitations on the constants I can generate in microcode, so some part of that range must be RAM.
- The interrupt vector should be kept at its current location ($00FFFE-$00FFFF) if possible, to avoid the need for microcode changes.
- ROM must be mapped to a 128K boundary.
- RAM must be mapped to a 512K boundary.
- ROM should ideally be mapped to a contiguous 128K address space, with no holes.
- RAM should ideally be mapped to a contiguous 512K address space, with none of it masked by ROM occupying the same space.
- Existing memory mappings should be changed as little as possible, to minimize the amount of software changes required.
A relatively logical mapping would have ROM at $000000 – $01FFFF, RAM at $F80000 – $FFFFFF, and devices somewhere like $020000 – $0200FF. However, I’d really like to avoid the microcode changes required if RAM is relocated, and I have some reason to suspect intermittent hardware glitches due to address bus signal noise if using bank $FF. Relocating RAM entirely from its current position would also require more software changes.
Instead, I’m planning to keep the existing mappings as they are, but add additional mappings for the same RAM and ROM at different address ranges, in order to meet the other requirements. So RAM and ROM will appear multiple times in the address space. This is a bit strange, and I may come to regret it, but I think it will solve my current problems with minimum impact. Essentially, ROM will be re-mapped to a currently unused address space in a contiguous 128K block, and RAM will be re-mapped to an unused contiguous 512K block. Existing microcode and hardware will continue to work as-is, but new software can take advantage of the new mappings to access additional ROM and previously-hidden RAM. The new memory mapping will look like this:
Range | Size | Contents |
---|---|---|
$000000 – $003EFF | 15.75K | ROM |
$003F00 – $003FFF | 256 bytes | memory-mapped devices |
$004000 – $07FFFF | 496K | RAM |
$080000 – $0FFFFF | 512K | mirror of RAM |
$100000 – $11FFFF | 128K | mirror of ROM |
$120000 – $1FFFFF | unused | |
$200000 – $207FFF | 32K | Video RAM |
$208000 – $FFFFFF | unused |
On a side note, the BMOW site has been receiving dramatically more visitors in the past week, after it was picked up on Hack-a-Day and Reddit. Hello to the new readers!
Read 3 comments and join the conversation3 Comments so far
Leave a reply. For customer support issues, please use the Customer Support link instead of writing comments.
Hello!
Nothing odd here. Your idea makes perfectly good sense to me. Especially since I recognize the typical methods an old friend used to do his work. That’s right I see the Apple influence at work here.
Probably you already know it, but I have to tell you anyway that you rock!
Next time you pull out BMOW 1, have some thought to having ROM mapped into the low 128K until you copy the menu into an area of RAM and transfer control to that, then use a memory mapped register to relocate the ROM, thus giving 512KB of continuous RAM from $000000 through $0FFFFF. I would put the ROM at the top of the address space after start up.
Sorry about so many comments, your work is an inspiration to my own. I am just sharing what I have learned, I can only hope that it may help.