Close

System registers in the I/O Reg space

A project log for YGREC8

A byte-wide stripped-down version of the YGREC16 architecture

yann-guidon-ygdesYann Guidon / YGDES 11/19/2023 at 02:390 Comments

The project progresses a lot !

The http://src.ygrec8.com/YGREC8/Manual/Y8-Manual.html is slowly getting more precise and pertinent thanks to help from @alcim.dev , Lionel and Kanna. The assembler is getting better but the simulator is the goal and it is obvious that certain core registers can't be accessed as usual, so they must be mapped to the IO registers space.

I have been cautious to not overdefine or over-allocate this pristine area, so far, but now is the time to start somewhere.

The basic model requires at least 4 8-bit registers:

Since they uniquely define the whole CPU state, they need "shadow" versions that are automatically saved during an interrupt or exception/trap. That makes 4*2=8 addresses that are mapped in the "negative" addresses, when bit 8 is set:

.EQU        A1BANK  -1 ; r/w
.EQU        A2BANK  -2 ; r/w
.EQU        CURROVL -3 ; ro
.EQU        FLAGS   -4 ; rw
.EQU SHADOW_A1BANK  -5 ; ro
.EQU SHADOW_A2BANK  -6 ; ro
.EQU SHADOW_CURROVL -7 ; ro
.EQU SHADOW_FLAGS   -8 ; ro

OK this doesn't seem practical because -8  falls outside of a 3-bit range (it amounts to 0). So let's offset things a bit with 7 other scratch registers, used to spill and/or save an interrupted state:

.EQU SCRATCH_A1     -1h ; r/w
.EQU SCRATCH_A2     -2h ; r/w
.EQU SCRATCH_R1     -3h ; r/w
.EQU SCRATCH_R2     -4h ; r/w
.EQU SCRATCH_R3     -5h ; r/w
.EQU SCRATCH        -6h ; r/w
.EQU        A1BANK  -7h ; r/w
.EQU        A2BANK  -8h ; r/w
.EQU        FLAGS   -Ah ; r/w
.EQU        CURROVL -9h ; ro (use the OVL opcode)
.EQU SHADOW_PC      -Bh ; ro
.EQU SHADOW_A1BANK  -Ch ; ro
.EQU SHADOW_A2BANK  -Dh ; ro
.EQU SHADOW_FLAGS   -Eh ; ro
.EQU SHADOW_CURROVL -Fh ; ro

This better version now includes a copy of the PC, as well as scratch registers that are used by a handler to save the state of a currently running program. One extra scratch register is provided, D1 and D2 are not saved because once you set the A1 and A2 registers, as well as the A1BANK and A2BANK registers, you can restore D1 and D2.

9 registers are read-write (including the A1BANK, A2BANK and FLAGS), the other 6 are read-only (for now). During a context save cyle:

A1BANK  => SHADOW_A1BANK
A2BANK  => SHADOW_A2BANK
FLAGS   => SHADOW_FLAGS
CURROVL => SHADOW_CURROVL
PC      => SHADOW_PC

Maybe one day there will be an instruction or other method to restore the registers back from their shadow. Yet so far, only A1BANK, A2BANK, FLAGS and CURROVL are strictly required for a basic implementation.

Beware : First restore  the AxBANK then only the Ax registers, to trigger a re-load of the Dx registers. Similarly, when changing the AxBANK, don't forget to update the Ax otherwise the Dx will contain data cached from writing to a different bank.

We need other registers to provide more awareness and flexibility. For example, the cause of arriving at address 0 of an overlay:

.EQU IO_A0CAUSE     -10h ; read, clear by writing 1s
; it's a bitfield:
.EQU CAUSE_RESET         1h;
.EQU CAUSE_OVL           2h;
.EQU CAUSE_TRAP          4h;
.EQU CAUSE_IRQ           8h;
.EQU CAUSE_INV          10h;
.EQU CAUSE_WATCHDOG     20h;
.EQU CAUSE_DOUBLEFAULT  40h;
.EQU CAUSE_OTHER        80h;

Another convenient feature for later is to address the IO space in sequence. The address is 9 bits wide so there is a need for 2 byte registers for the address, one with 7 unused bits. The choice is different: take a data register for the one half of the addressing space, another register for the other half.

.EQU IO_INDIRECT_PTR     -11h ; r/w, simple presetable counter
.EQU IO_INDIRECT_SYS     -12h ; r/w
.EQU IO_INDIRECT_USR     -13h ; r/w

Now we also need to define what these extended condition bits test: let's just allocate one whole 8-bit register for each condition, which can control a multiplexer or whatever.

.EQU IO_CONDITION_B0   -14h;
.EQU IO_CONDITION_B1   -15h;
.EQU IO_CONDITION_B2   -16h;
.EQU IO_CONDITION_B3   -17h;

The timers/counters will need much more registers than that, I don't even get started on the interrupt controller...


Concerning the rough allocation of the addresses:

Addresses 0 and above are left untouched for now.

So far we see the IO space split in two halves : the positive range (MSB=0) for user purpose and actual interfacing, with an open-ended and user-defined structure (where you put the GPIO, the serial links...), and the negative range will be more rigid and system-oriented (as above).

For simulations, we might want to read and write dummy data, for now it will go to address 42.

Discussions