By whygee on Tuesday 8 November 2011, 16:29 - Architecture
Warning : this is partially deprecated since 2013-08-09, see http://yasep.org/#!doc/reg-mem#parking
As the YASEP architecture specifies, there are 5 normal registers (R1-R5) and 5 pairs of data/address registers (A1-D1, A2-D2...) and it's quite difficult to find the right balance between both : each application and approach requires a different optimal number of registers.
When more registers are needed (if you need R6 or R7) then you could assign them to D1 and D2 for example. However you have to set A1 and A2 to a safe location otherwise chaos could propagate in the software. Another issue is that each write to the A registers will update the memory. A similar situation appears if we use the Ax registers as normal registers : each write will trigger a memory read. And in paged/protected memory systems, this would kill the TLB...
This is now "solved" with today's system, which defines hardwired "parking" addresses and internal behaviour (this is still preliminary but looking promising).
- "Parking" addresses are defined as "negative" addresses (that is : all the MSB are set to 1). This addressing range, at the "top" of the memory space, is normally not used, or used for special purposes, such as "fast constants" addressed by the short immediate values :
MOV -7, A3 ; mem[-7] contains a constant or a scratch value, MOV D3,... ; the address fits in 3 bits
- To keep the "parking" system compatible with non-parked versions, the
addresses are defined globally for all software. They are easy to remember, as
the following code shows :
; Park all the registers MOV -1, A1 MOV -2, A2 MOV -3, A3 MOV -4, A4 MOV -5, A5These will become macros or pseudo-instructions.
- The internal numbering of the registers is changed to ease hardware implementation. There is a direct match between the binary register number and the binary code of the address (bits 1 to 3) :
park address binary reg.bin reg.number register -1 1111 1111 15 A1 -2 1110 1101 13 A2 -3 1101 1011 11 A3 -4 1100 1001 9 A4 -5 1011 0111 7 A5
- Architecturally, it does not change much. The Data registers are "cached" by the register set. What the hardware parking system adds is just an inhibition of the "data write" signal that would occur normally each time the core writes to a D register.
- Aliasing : No alias detection is expected. If A4/D4 writes to -2, D2 is not updated. Otherwise it would mean that the result bus could write to 5 registers in parallel, which is not reasonable.
- Thread backup and restoration : the register set contains the cached version of the memory, it must be refreshed when a thread is restored (swapped in). If the Ax register matches a parked address, the memory doesn't need to be fetched to refresh the cache. Another solution is to save the Dx register through another Ax/Dx, so there is nothing to test during restoration (but memory read cycles could not be spared).
- This system where the "parking" is defined by an auxiliary value (that is inherently preserved through context switches) is "cleaner" than a more radical approach where "status bits" (one per A/D pair) park the registers. The advantage of the radical approach is that two registers can be parked at once (instead of one) but it gets harder to use with a compiler or from user software (you can play with pointers in C or Pascal easily, though you won't be able to define which pair is used). On top of that, adding status/control bits is usually a nightmare...
In the end, it's not very complex (not as much as it seems). The hardware price is a few logic gates that detect the parking addresses to inhibit memory writes. For the software writer, it just means more registers on demand and it will work whether the YASEP has the parking hardware or not. You CAN have R6, R7 or R8 but then you'll have to restrict data access and give up A1/D1, A2/D2 and A3/D3. You make the choice !
Parking was later modified and simplified. All the registers are parked at address #-1.
There must be a clever trick to implement it implicitly with a compiler... Register allocation is a key ;-)
Now I imagine that the data register writeback to memory should be triggered only when the address is changed... So a temporary data lifetime starts when the address is changed : this "flushes" the previous data in the register, "allocates" a new location and it's written/committed to memory when a new address is given. This moves the aliasing problem to somewhere else (due to simultaneous access by different pairs) but it's still worth investigating !
One thing is certain, though : new methods must be invented from scratch.