Given here (in roughly increasing order of difficulty) is a list of potential extensions you may want to consider for QuAC. Note that any extensions must be backwards compatible with the base ISA (you can’t redefine instructions that are already defined, for example). You may implement several extensions if you like (note that many of them are mutually exclusive, so some extensions will be incompatible with others) but we are seeking quality over quantity, especially with respect to the design document. It is far preferable to have one extension that is implemented cleanly and documented well, than many rushed extensions that are hard to follow.

Not all the extensions merely add extra instructions to the computer, but some fundamentally change architectural assumptions about the current design.

ALU Instructions

Adding additional ALU operations not included in the base ISA (NOT, XOR, logical shift, increment, decrement, etc).

I-Mode Memory Instructions

Allow a load directly from a specified memory location e.g. ldr rd, 0x12 would means that constants could be easily accessed, avoiding loading addresses into registers first. This is especially useful given the limited number of general purpose registers available.

Base+Offset Addressing

The other register slot in the encoding for load and store is unused. This could be extended to use a register as the base address, and either an immediate or another register as the offset address, allowing instructions like ldr/str rd, [ra,rb] which would have the effect of rd := [ra+rb] or [ra+rb] := rd as appropriate.

ALU Immediates

It’s frustrating to have to use up an extra register to increment a different register. Allowing operations with immediates would allow add r2, 1 directly, without having to first do movl r1, 1 or similar.

Can also synergise well with memory operations, ldr/str rd, [rb, 1] would allow easy access to different parts of a data structure stored at the address in rb.

Conditional Execution

As written, the ISA only conditionally executes on the Zero (Z) flag. You could extend this functionality such that the processor can execute on any arbitrary condition, such as the negative flag, or if one register was greater than another register, and so on.

For example, how could you extend the ISA to make it easy to execute the following code?

if x > y:
    z = x
else:
    z = y

Pre/Post Offset Memory Operations

When loading out values from an array of data, it’s often useful to have the ability to load from an address, and then increment that address afterwards to move to the next piece of data. This can be done with a pre-offset

ldr/str rd, [ra, rb]!

which is equivalent to

add ra, rb
ldr/str rd, [ra]

or a post-offset

ldr/str rd, [ra], rb

which is equivalent to

ldr/str rd, [ra]
add ra, rb

The difference here is that a pre/post offset takes only a single instruction cycle, whereas the two instructions it represents take two, which speeds execution of code.

Stack

You could define the reserved register as a stack pointer, define where the stack is in memory/what the bounds on it are/etc, and add instructions that allow a register to be pushed onto the stack, or allow data to be popped from the stack into a register.

Function Calls

(Requires: Stack)

Once a stack has been added, function calls are now also possible and could be implemented with composite instructions. call acts like a jp command overwriting the pc, but it also stores pc+1 onto the stack as a return address once the function has completed.

Bit Shifts

Multiple options here. Options could include:

  • 1-bit or N-bit shift(barrel)
  • Shift modes (logical, arithmetic, rotate)

mov and Number Manipulation

Broad class of potential extension instructions around numerical manipulation, centred around manipulating register values. Ideas here allow for 16 bit immediates to be loaded without using more register or immediate-addressable memory space.

  • swap - switch high and low bytes of a register
  • sext - sign-extend the value in a register, filling bits 15-9 with the contents of bit 8
  • movn - the more likely implementation of SEXT, move an 8 bit immediate to the low byte and sign extend the high byte - i.e. move negative

Expand Register File

The ISA as written only has 4 GP registers. This is fairly restrictive, and quite small as far as most CPUs go. Using reserved bits, could you add additional registers without fundamentally changing the instruction format to maintain backwards compatibility?

Dual-Ported Register File

(Synergy: Pre/Post offset)

The register file has two inputs, allowing two registers to be written to in the same cycle. If the same register is chosen for both destinations, then one takes precedence (so requires some priority negotiation). Useful for instructions like post offset load ldr rd, [ra], 1 that execute in only a single clock cycle.

I/O

The computer doesn’t have anything to talk to. You could add some built in components in Digital (a keyboard, a screen) and get the CPU to talk to those devices in a sensible fashion (either by adding dedicated I/O instructions, or mapping those devices to memory).

Multi-Cycle Execution

Up to this point the labs and the course have implicitly been leading you on a path to a single-cycle computer, one where each instruction is executed in a single clock cycle. This is unrealistic, as most real CPUs can often take a varying number of clock cycles depending on complexity.

Intermediate Registers

(Synergy: Multi-Cycle Execution)

Many complex instructions may take more than one cycle to execute. You could add intermediate registers that are only accessible by multi-cycle instructions to use as temporary scratch space without clobbering other registers. For example, call rd may be implemented as

add tmp, pc, 1
push tmp
mov pc, rd

Stack Instructions

(Requires: Stack)

You could define instructions that take zero operands, and operate directly onto the data on the stack e.g. addst or subst could pop the first two items off the stack, add/subtract them, and push the result back to the stack. This could be implemented with either the understanding that general purpose registers may be clobbered in the process, or by adding extra temporary registers that only stack instructions may use.

Extreme Ideas

We caution against the following extensions, and recommend them for only the bravest of students. Many of these require a fundamental redesign of the entire computer, and/or require research into topics we don’t cover. These extensions are not required for a HD mark, but are only included here for those that are interested.

Pipelining

As the computer currently stands, if we were to build it in hardware, it might be quite slow, as the computer waits until the entire instruction has been executed before trying to fetch the next one. A trick to speeding up a computer is called pipelining, where while the computer is executing the current instruction, it is also busy fetching the next instruction simultaneously. This can induce more problems, called hazards where executing a jump can mean the instruction fetched is the wrong one, or executing instructions that depend on the result from the previous instruction.

Multi-Core

The entire CPU can be duplicated, with two machines simultaneously reading and writing to the same memory. Semaphores are implemented to prevent memory from being clobbered by simultaneous writes. Likely requires knowledge from COMP2310 to complete.

Interrupts

(Requires: Stack, I/O)

The CPU can respond to urgent tasks (handling a keyboard press) by interrupting the current task it is working on, save its state somewhere, handle the urgent task, and then return to what it was doing afterwards.

Complex Hardware Instructions

Adding instructions that allow the CPU to multiply, divide, square root, etc, in hardware rather than writing a software algorithm to compute it.

Updated:    07 Feb 2023 / Responsible Officer:    Director, School of Computing / Page Contact:    Shoaib Akram