RISC Zero é uma arquitetura monociclo de uso geral com 16 registradores, construida para a disciplina de Prática em Organização de Computadores (SSC0119) da Universidade de São Paulo. Junto de seu esquemático do circuito, foram construídos um assembler e um simulador capazes de transformarem um código em Zassembly (Assembly da arquitetura RISC Zero) em um binário executável através do simulador. O projeto também possui um video explicativo que pode ser encontrado aqui!
- Barramentos de endereço de 16 bits.
- 16 registradores no total, sem contar o program counter (PC).
- Memória estruturada na forma Big Endian.
- Mapeamento dos dispositivos de entrada e saída diretamente na memória principal.
-
16 registradores expostos:
TMP(Usado pelo montador)HI(High)LO(Low)SP(Stack Pointer)ADR(Address)ACC(Acumulador)FLG(Flags)R1..R9(Registradores de uso geral)
-
Registradores ocultos:
PC(Program Counter)
RISC Zero possui 4 diferentes layouts de instruções, uma vez que cada uma empenha um papel diferente ao ser chamada:
-
Instrução tipo-R: Caracteriza-se por ser uma instrução de acesso à simultâneos registradores. Normalmente efetuando operações aritméticas e bit-a-bit.
-
Instrução tipo-I: Caracteriza-se por ser uma instrução que interage com um valor imediato. É utilizada também em operações aritméticas e para operações que suportam offsets.
-
Instrução tipo-M: Caracteriza-se por ser uma instrução de acesso à memória. Ou seja, é um tipo de instrução que se relaciona diretamente com registradores que representam endereços na memória princial (como o stack pointer).
-
Instrução tipo-J: Caracteriza-se por ser uma instrução de branching, ou de desvio, interrompendo o atual fluxo do programa e redirecionando-o para outro endereço.
Na tabela abaixo, podemos ver o mapeamento dos bits em cada modelo de instrução:
| Tipo / Bytes | OpCode | Reg1 | Reg2 | Im | Opts |
|---|---|---|---|---|---|
| R | 4 | 4 | 4 | - | 4 |
| I | 4 | 4 | - | 8 | - |
| M | 4 | 4 | 4 | 4 | - |
| J | 4 | 4 | - | - | 8 |
- Na borda de subida do clock, ocorre a leitura da instrução e sua decodificação.
- Na borda de descida, ocorre o write back.
Contendo uma gama de instruções, a arquitetura RISC Zero possui uma linguagem montadora plenamente funcional, possuindo suporte para definição de valores estáticos, macros, rótulos e funções. Além disso, pseudoinstruções muito úteis também podem ser encontradas em assembler/examples/stdio.zasm e assembler/examples/utils.zasm.
- [R]
ADD <reg1> <reg2>-reg1 += reg2 - [R]
SUB <reg1> <reg2>-reg1 -= reg2 - [R]
MULT <reg1> <reg2>-reg1 *= reg2 - [R]
DIV <reg1> <reg2>-HI = reg1 / reg2, LO = reg1 % reg2 - [R]
MOV <reg1> <reg2>-reg1 := reg2
- [R]
AND <reg1> <reg2>-reg1 &= reg2 - [R]
OR <reg1> <reg2>-reg1 |= reg2 - [R]
NOT <reg1>-reg1 = ~reg1 - [R]
SHL <reg1> <reg2>-reg1 <<= reg2 - [R]
SHR <reg1> <reg2>-reg1 >>= reg2
- [J]
BEQ <reg1>-if (ZERO) goto reg1 - [J]
BNE <reg1>-if (!ZERO) goto reg1 - [J]
BLT <reg1>-if (NEG) goto reg1 - [J]
BLE <reg1>-if (ZERO or NEG) goto reg1 - [J]
BGT <reg1>-if (!NEG) goto reg1 - [J]
BGE <reg1>-if (ZERO or !NEG) goto reg1 - [J]
JMP <reg1>-goto reg1
- [R]
CMP <reg1> <reg2>-ZERO := (reg1 == reg2), NEG := (reg1 < reg2)
- [M]
LDB <reg1> <im> <reg2>-reg1 := *(reg2 + im) - [M]
STB <reg1> <im> <reg2>-*(reg2 + im) := reg1 - [M]
LDW <reg1> <im> <reg2>-reg1 := *(int16_t *)(reg2 + im) - [M]
STW <reg1> <im> <reg2>-*(int16_t *)(reg2 + im) := reg1
- [I]
ANDI <reg1> <im>-reg1 &= im - [I]
ADDI <reg1> <im>-reg1 += im - [I]
LUI <reg1> <im>-reg1 = im << 8
| Instrução | OpCode | Tipo | Opts |
|---|---|---|---|
| NOOP | 0 | - | - |
| ADD | 1 | R | 0 |
| SUB | 1 | R | 1 |
| MULT | 1 | R | 2 |
| MOV | 1 | R | 3 |
| DIV | 1 | R | 4 |
| AND | 1 | R | 5 |
| OR | 1 | R | 6 |
| NOT | 1 | R | 7 |
| SHL | 1 | R | 8 |
| SHR | 1 | R | 9 |
| CMP | 1 | R | 10 |
| JMP | 2 | J | 0 |
| BEQ | 2 | J | 1 |
| BNE | 2 | J | 2 |
| BLT | 2 | J | 3 |
| BLE | 2 | J | 4 |
| BGT | 2 | J | 5 |
| BGE | 2 | J | 6 |
| ADDI | 3 | I | - |
| LUI | 4 | I | - |
| ANDI | 5 | I | - |
| Stw | 6 | M | - |
| Ldw | 7 | M | - |
| Stb | 8 | M | - |
| Ldb | 9 | M | - |
| Int | 10 | - | - |
| Hlt | 11 | - | - |
| Registrador | Valor |
|---|---|
| TMP | 0 |
| HI | 1 |
| LO | 2 |
| SP | 3 |
| ADR | 4 |
| ACC | 5 |
| FL | 6 |
| R1 | 7 |
| R2 | 8 |
| R3 | 9 |
| R4 | 10 |
| R5 | 11 |
| R6 | 12 |
| R7 | 13 |
| R8 | 14 |
| R9 | 15 |
A entrada/saída de dados através dos dispositivos de entrada/saída
é feita a partir da instrução INT (Interrupt), que atua como uma
chamada do sistema operacinal (syscall) a partir do que estiver no
registrador de acumulação.
ACC == 1: READ_CHAR,ACC == 2: READ_INTEGER,ACC == 3: PRINT_CHARACC == 4: PRINT_DECIMALACC == 5: PRINT_BINARYACC == 6: PRINT_HEX,
O resultado lido/imprimido na tela é sempre relativo ao registrador R1.
